relay-runtime 20.1.1 → 21.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.
Files changed (262) hide show
  1. package/experimental.js +1 -1
  2. package/experimental.js.flow +8 -8
  3. package/handlers/connection/ConnectionHandler.js.flow +5 -5
  4. package/handlers/connection/ConnectionInterface.js.flow +1 -1
  5. package/index.js +1 -1
  6. package/index.js.flow +125 -62
  7. package/lib/experimental.js +3 -3
  8. package/lib/index.js +105 -57
  9. package/lib/multi-actor-environment/ActorIdentifier.js +2 -2
  10. package/lib/multi-actor-environment/MultiActorEnvironment.js +3 -1
  11. package/lib/mutations/commitMutation.js +8 -8
  12. package/lib/mutations/validateMutation.js +4 -4
  13. package/lib/query/GraphQLTag.js +3 -3
  14. package/lib/query/fetchQuery.js +15 -3
  15. package/lib/store/DataChecker.js +38 -4
  16. package/lib/store/NormalizationEngine.js +373 -0
  17. package/lib/store/OperationExecutor.js +172 -113
  18. package/lib/store/RelayConcreteVariables.js +1 -1
  19. package/lib/store/RelayErrorTrie.js +2 -2
  20. package/lib/store/RelayExperimentalGraphResponseTransform.js +8 -8
  21. package/lib/store/RelayModernEnvironment.js +26 -19
  22. package/lib/store/RelayModernRecord.js +18 -8
  23. package/lib/store/RelayModernSelector.js +9 -9
  24. package/lib/store/RelayModernStore.js +152 -43
  25. package/lib/store/RelayPublishQueue.js +1 -1
  26. package/lib/store/RelayReader.js +76 -38
  27. package/lib/store/RelayRecordSource.js +6 -0
  28. package/lib/store/RelayReferenceMarker.js +2 -1
  29. package/lib/store/RelayResponseNormalizer.js +88 -55
  30. package/lib/store/RelayStoreSubscriptions.js +34 -10
  31. package/lib/store/RelayStoreUtils.js +8 -1
  32. package/lib/store/ResolverFragments.js +2 -2
  33. package/lib/store/live-resolvers/LiveResolverCache.js +25 -9
  34. package/lib/store/observeFragmentExperimental.js +17 -1
  35. package/lib/store/observeQueryExperimental.js +2 -2
  36. package/lib/subscription/requestSubscription.js +3 -3
  37. package/lib/util/RelayError.js +3 -0
  38. package/lib/util/RelayFeatureFlags.js +6 -2
  39. package/lib/util/RelayReplaySubject.js +4 -4
  40. package/lib/util/handlePotentialSnapshotErrors.js +2 -2
  41. package/lib/util/stableCopy.js +2 -2
  42. package/llm-docs/api-reference/entrypoint-apis/entrypoint-container.mdx +38 -0
  43. package/llm-docs/api-reference/entrypoint-apis/load-entrypoint.mdx +77 -0
  44. package/llm-docs/api-reference/entrypoint-apis/use-entrypoint-loader.mdx +99 -0
  45. package/llm-docs/api-reference/graphql/graphql-directives.mdx +378 -0
  46. package/llm-docs/api-reference/hooks/_use-lazy-load-query-extra.mdx +16 -0
  47. package/llm-docs/api-reference/hooks/load-query.mdx +84 -0
  48. package/llm-docs/api-reference/hooks/relay-environment-provider.mdx +78 -0
  49. package/llm-docs/api-reference/hooks/use-client-query.mdx +65 -0
  50. package/llm-docs/api-reference/hooks/use-fragment.mdx +69 -0
  51. package/llm-docs/api-reference/hooks/use-lazy-load-query.mdx +62 -0
  52. package/llm-docs/api-reference/hooks/use-mutation.mdx +94 -0
  53. package/llm-docs/api-reference/hooks/use-pagination-fragment.mdx +166 -0
  54. package/llm-docs/api-reference/hooks/use-prefetchable-forward-pagination-fragment.mdx +134 -0
  55. package/llm-docs/api-reference/hooks/use-preloaded-query.mdx +84 -0
  56. package/llm-docs/api-reference/hooks/use-query-loader.mdx +95 -0
  57. package/llm-docs/api-reference/hooks/use-refetchable-fragment.mdx +122 -0
  58. package/llm-docs/api-reference/hooks/use-relay-environment.mdx +37 -0
  59. package/llm-docs/api-reference/hooks/use-subscription.mdx +66 -0
  60. package/llm-docs/api-reference/relay-resolvers/docblock-format.mdx +321 -0
  61. package/llm-docs/api-reference/relay-resolvers/runtime-functions.mdx +94 -0
  62. package/llm-docs/api-reference/relay-runtime/commit-mutation.mdx +65 -0
  63. package/llm-docs/api-reference/relay-runtime/fetch-query.mdx +113 -0
  64. package/llm-docs/api-reference/relay-runtime/field-logger.mdx +170 -0
  65. package/llm-docs/api-reference/relay-runtime/observe-fragment.mdx +92 -0
  66. package/llm-docs/api-reference/relay-runtime/relay-environment.mdx +53 -0
  67. package/llm-docs/api-reference/relay-runtime/request-subscription.mdx +54 -0
  68. package/llm-docs/api-reference/relay-runtime/runtime-configuration.mdx +52 -0
  69. package/llm-docs/api-reference/relay-runtime/store.mdx +734 -0
  70. package/llm-docs/api-reference/relay-runtime/wait-for-fragment-data.mdx +89 -0
  71. package/llm-docs/api-reference/types/CacheConfig.mdx +8 -0
  72. package/llm-docs/api-reference/types/Disposable.mdx +4 -0
  73. package/llm-docs/api-reference/types/GraphQLSubscriptionConfig.mdx +17 -0
  74. package/llm-docs/api-reference/types/MutationConfig.mdx +31 -0
  75. package/llm-docs/api-reference/types/SelectorStoreUpdater.mdx +6 -0
  76. package/llm-docs/api-reference/types/UploadableMap.mdx +3 -0
  77. package/llm-docs/community/learning-resources.mdx +64 -0
  78. package/llm-docs/debugging/declarative-mutation-directives.mdx +34 -0
  79. package/llm-docs/debugging/disallowed-id-types-error.mdx +43 -0
  80. package/llm-docs/debugging/inconsistent-typename-error.mdx +47 -0
  81. package/llm-docs/debugging/relay-devtools.mdx +73 -0
  82. package/llm-docs/debugging/why-null.mdx +116 -0
  83. package/llm-docs/editor-support.mdx +55 -0
  84. package/llm-docs/error-reference/unknown-field.mdx +36 -0
  85. package/llm-docs/getting-started/babel-plugin.mdx +31 -0
  86. package/llm-docs/getting-started/compiler-config.mdx +25 -0
  87. package/llm-docs/getting-started/compiler.mdx +82 -0
  88. package/llm-docs/getting-started/lint-rules.mdx +87 -0
  89. package/llm-docs/getting-started/production.mdx +30 -0
  90. package/llm-docs/getting-started/quick-start.mdx +213 -0
  91. package/llm-docs/glossary/glossary.mdx +1040 -0
  92. package/llm-docs/guided-tour/list-data/advanced-pagination.mdx +157 -0
  93. package/llm-docs/guided-tour/list-data/connections.mdx +81 -0
  94. package/llm-docs/guided-tour/list-data/pagination.mdx +193 -0
  95. package/llm-docs/guided-tour/list-data/rendering-connections.mdx +112 -0
  96. package/llm-docs/guided-tour/list-data/streaming-pagination.mdx +87 -0
  97. package/llm-docs/guided-tour/managing-data-outside-react/retaining-queries.mdx +51 -0
  98. package/llm-docs/guided-tour/refetching/refetching-queries-with-different-data.mdx +337 -0
  99. package/llm-docs/guided-tour/refetching/refreshing-queries.mdx +350 -0
  100. package/llm-docs/guided-tour/rendering/environment.mdx +59 -0
  101. package/llm-docs/guided-tour/rendering/error-states.mdx +295 -0
  102. package/llm-docs/guided-tour/rendering/fragments.mdx +354 -0
  103. package/llm-docs/guided-tour/rendering/loading-states.mdx +245 -0
  104. package/llm-docs/guided-tour/rendering/queries.mdx +261 -0
  105. package/llm-docs/guided-tour/rendering/variables.mdx +233 -0
  106. package/llm-docs/guided-tour/reusing-cached-data/fetch-policies.mdx +56 -0
  107. package/llm-docs/guided-tour/reusing-cached-data/filling-in-missing-data.mdx +102 -0
  108. package/llm-docs/guided-tour/reusing-cached-data/introduction.mdx +22 -0
  109. package/llm-docs/guided-tour/reusing-cached-data/presence-of-data.mdx +93 -0
  110. package/llm-docs/guided-tour/reusing-cached-data/rendering-partially-cached-data.mdx +175 -0
  111. package/llm-docs/guided-tour/reusing-cached-data/staleness-of-data.mdx +116 -0
  112. package/llm-docs/guided-tour/updating-data/client-only-data.mdx +115 -0
  113. package/llm-docs/guided-tour/updating-data/graphql-mutations.mdx +334 -0
  114. package/llm-docs/guided-tour/updating-data/graphql-subscriptions.mdx +279 -0
  115. package/llm-docs/guided-tour/updating-data/imperatively-modifying-linked-fields.mdx +511 -0
  116. package/llm-docs/guided-tour/updating-data/imperatively-modifying-store-data-legacy.mdx +142 -0
  117. package/llm-docs/guided-tour/updating-data/imperatively-modifying-store-data.mdx +275 -0
  118. package/llm-docs/guided-tour/updating-data/introduction.mdx +25 -0
  119. package/llm-docs/guided-tour/updating-data/local-data-updates.mdx +71 -0
  120. package/llm-docs/guided-tour/updating-data/typesafe-updaters-faq.mdx +83 -0
  121. package/llm-docs/guided-tour/updating-data/updating-connections.mdx +592 -0
  122. package/llm-docs/guides/alias-directive.mdx +160 -0
  123. package/llm-docs/guides/catch-directive.mdx +167 -0
  124. package/llm-docs/guides/client-schema-extensions.mdx +208 -0
  125. package/llm-docs/guides/codemods.mdx +66 -0
  126. package/llm-docs/guides/data-driven-dependencies/client-3d.mdx +255 -0
  127. package/llm-docs/guides/data-driven-dependencies/configuration.mdx +127 -0
  128. package/llm-docs/guides/data-driven-dependencies/introduction.mdx +39 -0
  129. package/llm-docs/guides/data-driven-dependencies/server-3d.mdx +664 -0
  130. package/llm-docs/guides/document-comparison.mdx +106 -0
  131. package/llm-docs/guides/graphql-server-specification.mdx +453 -0
  132. package/llm-docs/guides/network-layer.mdx +69 -0
  133. package/llm-docs/guides/persisted-queries.mdx +328 -0
  134. package/llm-docs/guides/relay-resolvers/context.mdx +99 -0
  135. package/llm-docs/guides/relay-resolvers/defining-fields.mdx +151 -0
  136. package/llm-docs/guides/relay-resolvers/defining-types.mdx +164 -0
  137. package/llm-docs/guides/relay-resolvers/deprecated.mdx +27 -0
  138. package/llm-docs/guides/relay-resolvers/derived-fields.mdx +127 -0
  139. package/llm-docs/guides/relay-resolvers/descriptions.mdx +44 -0
  140. package/llm-docs/guides/relay-resolvers/enabling.mdx +41 -0
  141. package/llm-docs/guides/relay-resolvers/errors.mdx +64 -0
  142. package/llm-docs/guides/relay-resolvers/field-arguments.mdx +63 -0
  143. package/llm-docs/guides/relay-resolvers/introduction.mdx +62 -0
  144. package/llm-docs/guides/relay-resolvers/limitations.mdx +30 -0
  145. package/llm-docs/guides/relay-resolvers/live-fields.mdx +164 -0
  146. package/llm-docs/guides/relay-resolvers/return-types.mdx +161 -0
  147. package/llm-docs/guides/relay-resolvers/suspense.mdx +41 -0
  148. package/llm-docs/guides/required-directive.mdx +240 -0
  149. package/llm-docs/guides/semantic-nullability.mdx +93 -0
  150. package/llm-docs/guides/testing-relay-components.mdx +642 -0
  151. package/llm-docs/guides/testing-relay-with-preloaded-queries.mdx +160 -0
  152. package/llm-docs/guides/throw-on-field-error-directive.mdx +58 -0
  153. package/llm-docs/guides/type-emission.mdx +414 -0
  154. package/llm-docs/home.mdx +32 -0
  155. package/llm-docs/principles-and-architecture/architecture-overview.mdx +24 -0
  156. package/llm-docs/principles-and-architecture/compiler-architecture.mdx +106 -0
  157. package/llm-docs/principles-and-architecture/runtime-architecture.mdx +249 -0
  158. package/llm-docs/principles-and-architecture/thinking-in-graphql.mdx +309 -0
  159. package/llm-docs/principles-and-architecture/thinking-in-relay.mdx +104 -0
  160. package/llm-docs/principles-and-architecture/videos.mdx +50 -0
  161. package/llm-docs/tutorial/arrays-lists.mdx +126 -0
  162. package/llm-docs/tutorial/fragments-1.mdx +487 -0
  163. package/llm-docs/tutorial/graphql.mdx +172 -0
  164. package/llm-docs/tutorial/interfaces-polymorphism.mdx +161 -0
  165. package/llm-docs/tutorial/intro.mdx +58 -0
  166. package/llm-docs/tutorial/mutations-updates.mdx +624 -0
  167. package/llm-docs/tutorial/organizing-mutations-queries-and-subscriptions.mdx +13 -0
  168. package/llm-docs/tutorial/queries-1.mdx +267 -0
  169. package/llm-docs/tutorial/queries-2.mdx +389 -0
  170. package/llm-docs/tutorial/refetchable-fragments.mdx +352 -0
  171. package/multi-actor-environment/ActorIdentifier.js.flow +2 -2
  172. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +7 -7
  173. package/multi-actor-environment/ActorUtils.js.flow +1 -1
  174. package/multi-actor-environment/MultiActorEnvironment.js.flow +12 -8
  175. package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +3 -3
  176. package/mutations/RelayDeclarativeMutationConfig.js.flow +9 -9
  177. package/mutations/RelayRecordProxy.js.flow +8 -11
  178. package/mutations/RelayRecordSourceMutator.js.flow +4 -4
  179. package/mutations/RelayRecordSourceProxy.js.flow +4 -4
  180. package/mutations/RelayRecordSourceSelectorProxy.js.flow +6 -6
  181. package/mutations/applyOptimisticMutation.js.flow +2 -2
  182. package/mutations/commitMutation.js.flow +20 -16
  183. package/mutations/createUpdatableProxy.js.flow +19 -19
  184. package/mutations/readUpdatableFragment.js.flow +3 -3
  185. package/mutations/readUpdatableQuery.js.flow +3 -3
  186. package/mutations/validateMutation.js.flow +7 -7
  187. package/network/RelayNetworkTypes.js.flow +4 -4
  188. package/network/RelayObservable.js.flow +16 -14
  189. package/network/RelayQueryResponseCache.js.flow +3 -3
  190. package/network/wrapNetworkWithLogObserver.js.flow +1 -1
  191. package/package.json +2 -1
  192. package/query/GraphQLTag.js.flow +22 -10
  193. package/query/fetchQuery.js.flow +23 -10
  194. package/query/fetchQuery_DEPRECATED.js.flow +1 -1
  195. package/store/DataChecker.js.flow +43 -9
  196. package/store/NormalizationEngine.js.flow +779 -0
  197. package/store/OperationExecutor.js.flow +173 -70
  198. package/store/RelayConcreteVariables.js.flow +5 -5
  199. package/store/RelayErrorTrie.js.flow +12 -12
  200. package/store/RelayExperimentalGraphResponseHandler.js.flow +3 -3
  201. package/store/RelayExperimentalGraphResponseTransform.js.flow +10 -10
  202. package/store/RelayModernEnvironment.js.flow +41 -26
  203. package/store/RelayModernFragmentSpecResolver.js.flow +1 -1
  204. package/store/RelayModernOperationDescriptor.js.flow +1 -1
  205. package/store/RelayModernRecord.js.flow +44 -20
  206. package/store/RelayModernSelector.js.flow +21 -21
  207. package/store/RelayModernStore.js.flow +219 -58
  208. package/store/RelayOperationTracker.js.flow +2 -2
  209. package/store/RelayOptimisticRecordSource.js.flow +2 -2
  210. package/store/RelayPublishQueue.js.flow +21 -12
  211. package/store/RelayReader.js.flow +129 -57
  212. package/store/RelayRecordSource.js.flow +10 -0
  213. package/store/RelayRecordState.js.flow +1 -1
  214. package/store/RelayReferenceMarker.js.flow +5 -4
  215. package/store/RelayResponseNormalizer.js.flow +125 -57
  216. package/store/RelayStoreSubscriptions.js.flow +52 -8
  217. package/store/RelayStoreTypes.js.flow +153 -64
  218. package/store/RelayStoreUtils.js.flow +15 -7
  219. package/store/ResolverCache.js.flow +2 -2
  220. package/store/ResolverFragments.js.flow +12 -12
  221. package/store/StoreInspector.js.flow +6 -7
  222. package/store/cloneRelayHandleSourceField.js.flow +1 -1
  223. package/store/cloneRelayScalarHandleSourceField.js.flow +1 -1
  224. package/store/createRelayContext.js.flow +1 -1
  225. package/store/createRelayLoggingContext.js.flow +4 -4
  226. package/store/defaultGetDataID.js.flow +2 -2
  227. package/store/isRelayModernEnvironment.js.flow +4 -2
  228. package/store/live-resolvers/LiveResolverCache.js.flow +55 -20
  229. package/store/live-resolvers/LiveResolverSuspenseSentinel.js.flow +3 -3
  230. package/store/live-resolvers/getOutputTypeRecordIDs.js.flow +1 -1
  231. package/store/live-resolvers/isLiveStateValue.js.flow +2 -2
  232. package/store/live-resolvers/resolverDataInjector.js.flow +8 -5
  233. package/store/observeFragmentExperimental.js.flow +49 -20
  234. package/store/observeQueryExperimental.js.flow +5 -5
  235. package/store/readInlineData.js.flow +4 -4
  236. package/store/waitForFragmentExperimental.js.flow +3 -3
  237. package/subscription/requestSubscription.js.flow +7 -7
  238. package/util/NormalizationNode.js.flow +34 -32
  239. package/util/ReaderNode.js.flow +32 -30
  240. package/util/RelayConcreteNode.js.flow +5 -5
  241. package/util/RelayError.js.flow +4 -1
  242. package/util/RelayFeatureFlags.js.flow +21 -1
  243. package/util/RelayProfiler.js.flow +1 -1
  244. package/util/RelayReplaySubject.js.flow +3 -3
  245. package/util/RelayRuntimeTypes.js.flow +11 -11
  246. package/util/createPayloadFor3DField.js.flow +9 -5
  247. package/util/deepFreeze.js.flow +2 -2
  248. package/util/getFragmentIdentifier.js.flow +1 -1
  249. package/util/getPaginationMetadata.js.flow +1 -1
  250. package/util/getPaginationVariables.js.flow +1 -1
  251. package/util/getPendingOperationsForFragment.js.flow +2 -2
  252. package/util/getRefetchMetadata.js.flow +6 -5
  253. package/util/getValueAtPath.js.flow +3 -3
  254. package/util/handlePotentialSnapshotErrors.js.flow +5 -5
  255. package/util/isEmptyObject.js.flow +1 -1
  256. package/util/isPromise.js.flow +2 -2
  257. package/util/isScalarAndEqual.js.flow +1 -1
  258. package/util/recycleNodesInto.js.flow +2 -2
  259. package/util/registerEnvironmentWithDevTools.js.flow +1 -1
  260. package/util/shallowFreeze.js.flow +1 -1
  261. package/util/stableCopy.js.flow +5 -5
  262. package/util/withProvidedVariables.js.flow +14 -10
@@ -32,8 +32,8 @@ export type EvaluationResult<T> = {
32
32
  error: ?Error,
33
33
  };
34
34
 
35
- export type ResolverFragmentResult = $ReadOnly<{
36
- data: mixed,
35
+ export type ResolverFragmentResult = Readonly<{
36
+ data: unknown,
37
37
  isMissingData: boolean,
38
38
  fieldErrors: ?FieldErrors,
39
39
  }>;
@@ -52,33 +52,33 @@ function withResolverContext<T>(context: ResolverContext, cb: () => T): T {
52
52
  // - array of nullable if the provided ref type is an array of nullable refs
53
53
 
54
54
  declare function readFragment<
55
- TKey: {+$data?: mixed, +$fragmentSpreads: FragmentType, ...},
55
+ TKey extends {+$data?: unknown, +$fragmentSpreads: FragmentType, ...},
56
56
  >(
57
57
  fragmentInput: GraphQLTaggedNode,
58
58
  fragmentKey: TKey,
59
- ): $NonMaybeType<TKey['$data']>;
59
+ ): NonNullable<TKey['$data']>;
60
60
 
61
61
  declare function readFragment<
62
- TKey: ?{+$data?: mixed, +$fragmentSpreads: FragmentType, ...},
62
+ TKey extends ?{+$data?: unknown, +$fragmentSpreads: FragmentType, ...},
63
63
  >(
64
64
  fragmentInput: GraphQLTaggedNode,
65
65
  fragmentKey: TKey,
66
66
  ): ?TKey?.['$data'];
67
67
 
68
68
  declare function readFragment<
69
- TKey: $ReadOnlyArray<{
70
- +$data?: mixed,
69
+ TKey extends ReadonlyArray<{
70
+ +$data?: unknown,
71
71
  +$fragmentSpreads: FragmentType,
72
72
  ...
73
73
  }>,
74
74
  >(
75
75
  fragmentInput: GraphQLTaggedNode,
76
76
  fragmentKey: TKey,
77
- ): $NonMaybeType<TKey[number]['$data']>;
77
+ ): NonNullable<TKey[number]['$data']>;
78
78
 
79
79
  declare function readFragment<
80
- TKey: ?$ReadOnlyArray<{
81
- +$data?: mixed,
80
+ TKey extends ?ReadonlyArray<{
81
+ +$data?: unknown,
82
82
  +$fragmentSpreads: FragmentType,
83
83
  ...
84
84
  }>,
@@ -87,7 +87,7 @@ declare function readFragment<
87
87
  fragmentKey: TKey,
88
88
  ): ?TKey?.[number]['$data'];
89
89
 
90
- declare function readFragment<TKey: FragmentType, TData>(
90
+ declare function readFragment<TKey extends FragmentType, TData>(
91
91
  fragmentInput: Fragment<TKey, TData>,
92
92
  fragmentKey: TKey,
93
93
  ): TData;
@@ -95,7 +95,7 @@ declare function readFragment<TKey: FragmentType, TData>(
95
95
  function readFragment(
96
96
  fragmentInput: GraphQLTaggedNode,
97
97
  fragmentKey: FragmentType,
98
- ): mixed {
98
+ ): unknown {
99
99
  if (!contextStack.length) {
100
100
  throw new Error(
101
101
  'readFragment should be called only from within a Relay Resolver function.',
@@ -127,10 +127,10 @@ function readFragment(
127
127
  return data;
128
128
  }
129
129
 
130
- const RESOLVER_FRAGMENT_ERRORED_SENTINEL: mixed = {};
130
+ const RESOLVER_FRAGMENT_ERRORED_SENTINEL: unknown = {};
131
131
 
132
132
  module.exports = {
133
+ RESOLVER_FRAGMENT_ERRORED_SENTINEL,
133
134
  readFragment,
134
135
  withResolverContext,
135
- RESOLVER_FRAGMENT_ERRORED_SENTINEL,
136
136
  };
@@ -13,7 +13,7 @@
13
13
 
14
14
  import type {IEnvironment, RecordSource} from '../store/RelayStoreTypes';
15
15
 
16
- type InspectFn = (environment: IEnvironment, dataID?: ?string) => mixed;
16
+ type InspectFn = (environment: IEnvironment, dataID?: ?string) => unknown;
17
17
 
18
18
  let inspect: InspectFn = () => {};
19
19
 
@@ -81,8 +81,8 @@ if (__DEV__) {
81
81
 
82
82
  class RecordEntry {
83
83
  +key: string;
84
- +value: mixed;
85
- constructor(key: string, value: mixed) {
84
+ +value: unknown;
85
+ constructor(key: string, value: unknown) {
86
86
  this.key = key;
87
87
  this.value = value;
88
88
  }
@@ -138,14 +138,13 @@ if (__DEV__) {
138
138
  const getWrappedRecord = (
139
139
  source: RecordSource,
140
140
  dataID: string,
141
- ): ?{[string]: mixed} => {
141
+ ): ?{[string]: unknown} => {
142
142
  const record = source.get(dataID);
143
143
  if (record == null) {
144
- // $FlowFixMe[incompatible-return]
144
+ // $FlowFixMe[incompatible-type]
145
145
  return record;
146
146
  }
147
147
  return new Proxy(
148
- // $FlowFixMe: Do not assume that record is an object
149
148
  {...record},
150
149
  {
151
150
  get(target, prop) {
@@ -159,7 +158,7 @@ if (__DEV__) {
159
158
  return getWrappedRecord(source, value.__ref);
160
159
  }
161
160
  if (Array.isArray(value.__refs)) {
162
- // $FlowFixMe[incompatible-call]
161
+ // $FlowFixMe[incompatible-type]
163
162
  return value.__refs.map((ref: string) =>
164
163
  getWrappedRecord(source, ref),
165
164
  );
@@ -32,7 +32,7 @@ const invariant = require('invariant');
32
32
  */
33
33
  function cloneRelayHandleSourceField(
34
34
  handleField: NormalizationLinkedHandle,
35
- selections: $ReadOnlyArray<NormalizationSelection>,
35
+ selections: ReadonlyArray<NormalizationSelection>,
36
36
  variables: Variables,
37
37
  ): NormalizationLinkedField {
38
38
  const sourceField = selections.find(
@@ -31,7 +31,7 @@ const invariant = require('invariant');
31
31
  */
32
32
  function cloneRelayScalarHandleSourceField(
33
33
  handleField: NormalizationScalarHandle,
34
- selections: $ReadOnlyArray<NormalizationSelection>,
34
+ selections: ReadonlyArray<NormalizationSelection>,
35
35
  variables: Variables,
36
36
  ): NormalizationScalarField {
37
37
  const sourceField = selections.find(
@@ -19,7 +19,7 @@ const invariant = require('invariant');
19
19
 
20
20
  // Ideally, we'd just import the type of the react module, but this causes Flow
21
21
  // problems.
22
- type React = $ReadOnly<{
22
+ type React = Readonly<{
23
23
  createContext: createContext<RelayContext | null>,
24
24
  version: string,
25
25
  ...
@@ -18,16 +18,16 @@ const invariant = require('invariant');
18
18
 
19
19
  // Ideally, we'd just import the type of the react module, but this causes Flow
20
20
  // problems.
21
- type React = $ReadOnly<{
22
- createContext: createContext<mixed | null>,
21
+ type React = Readonly<{
22
+ createContext: createContext<unknown | null>,
23
23
  version: string,
24
24
  ...
25
25
  }>;
26
26
 
27
- let relayLoggingContext: ?Context<mixed | null>;
27
+ let relayLoggingContext: ?Context<unknown | null>;
28
28
  let firstReact: ?React;
29
29
 
30
- function createRelayLoggingContext(react: React): Context<mixed | null> {
30
+ function createRelayLoggingContext(react: React): Context<unknown | null> {
31
31
  if (!relayLoggingContext) {
32
32
  relayLoggingContext = react.createContext(null);
33
33
  if (__DEV__) {
@@ -14,9 +14,9 @@
14
14
  const {VIEWER_ID, VIEWER_TYPE} = require('./ViewerPattern');
15
15
 
16
16
  function defaultGetDataID(
17
- fieldValue: {+[string]: mixed},
17
+ fieldValue: {+[string]: unknown},
18
18
  typeName: string,
19
- ): mixed {
19
+ ): unknown {
20
20
  if (typeName === VIEWER_TYPE) {
21
21
  return fieldValue.id == null ? VIEWER_ID : fieldValue.id;
22
22
  }
@@ -19,8 +19,10 @@
19
19
  * aid in module tree-shaking to avoid requiring all of RelayRuntime just to
20
20
  * detect its environment.
21
21
  */
22
- function isRelayModernEnvironment(environment: mixed): boolean {
23
- return Boolean(environment && (environment: any)['@@RelayModernEnvironment']);
22
+ function isRelayModernEnvironment(environment: unknown): boolean {
23
+ return Boolean(
24
+ environment && (environment as any)['@@RelayModernEnvironment'],
25
+ );
24
26
  }
25
27
 
26
28
  module.exports = isRelayModernEnvironment;
@@ -46,6 +46,7 @@ const {
46
46
  RELAY_RESOLVER_ERROR_KEY,
47
47
  RELAY_RESOLVER_INVALIDATION_KEY,
48
48
  RELAY_RESOLVER_OUTPUT_TYPE_RECORD_IDS,
49
+ RELAY_RESOLVER_RECORD_TYPENAME,
49
50
  RELAY_RESOLVER_SNAPSHOT_KEY,
50
51
  RELAY_RESOLVER_VALUE_KEY,
51
52
  getReadTimeResolverStorageKey,
@@ -63,7 +64,6 @@ const RELAY_RESOLVER_LIVE_STATE_SUBSCRIPTION_KEY =
63
64
  '__resolverLiveStateSubscription';
64
65
  const RELAY_RESOLVER_LIVE_STATE_VALUE = '__resolverLiveStateValue';
65
66
  const RELAY_RESOLVER_LIVE_STATE_DIRTY = '__resolverLiveStateDirty';
66
- const RELAY_RESOLVER_RECORD_TYPENAME = '__RELAY_RESOLVER__';
67
67
  const MODEL_PROPERTY_NAME = '__relay_model_instance';
68
68
 
69
69
  /**
@@ -181,7 +181,7 @@ class LiveResolverCache implements ResolverCache {
181
181
  evaluationResult.error == null,
182
182
  'Did not expect resolver to have both a value and an error.',
183
183
  );
184
- const liveState: LiveState<mixed> =
184
+ const liveState: LiveState<unknown> =
185
185
  // $FlowFixMe[incompatible-type] - casting mixed
186
186
  evaluationResult.resolverResult;
187
187
  updatedDataIDs = this._setLiveStateValue(
@@ -261,7 +261,7 @@ class LiveResolverCache implements ResolverCache {
261
261
  linkedID = linkedID ?? generateClientID(recordID, storageKey);
262
262
  linkedRecord = RelayModernRecord.clone(linkedRecord);
263
263
  // $FlowFixMe[incompatible-type] - casting mixed
264
- const liveState: LiveState<mixed> = RelayModernRecord.getValue(
264
+ const liveState: LiveState<unknown> = RelayModernRecord.getValue(
265
265
  linkedRecord,
266
266
  RELAY_RESOLVER_LIVE_STATE_VALUE,
267
267
  );
@@ -327,7 +327,7 @@ class LiveResolverCache implements ResolverCache {
327
327
  );
328
328
 
329
329
  // $FlowFixMe[incompatible-type] - casting mixed
330
- const liveState: LiveState<mixed> = RelayModernRecord.getValue(
330
+ const liveState: LiveState<unknown> = RelayModernRecord.getValue(
331
331
  liveStateRecord,
332
332
  RELAY_RESOLVER_LIVE_STATE_VALUE,
333
333
  );
@@ -345,7 +345,7 @@ class LiveResolverCache implements ResolverCache {
345
345
  _setLiveStateValue(
346
346
  linkedRecord: Record,
347
347
  linkedID: DataID,
348
- liveState: LiveState<mixed>,
348
+ liveState: LiveState<unknown>,
349
349
  field: ReaderRelayLiveResolver,
350
350
  variables: Variables,
351
351
  ): DataIDSet | null {
@@ -474,14 +474,39 @@ class LiveResolverCache implements ResolverCache {
474
474
  }
475
475
  }
476
476
 
477
+ // Returns true if source is published
478
+ batchLiveStateUpdatesWithoutNotify(callback: () => void): boolean {
479
+ invariant(
480
+ !this._handlingBatch,
481
+ 'Unexpected nested call to batchLiveStateUpdates.',
482
+ );
483
+ this._handlingBatch = true;
484
+ try {
485
+ callback();
486
+ } finally {
487
+ const shouldPublish = this._liveResolverBatchRecordSource != null;
488
+ // We lazily create the record source. If one has not been created, there
489
+ // is nothing to publish.
490
+ if (shouldPublish) {
491
+ // $FlowFixMe[incompatible-type] Null checked
492
+ this._store.publish(this._liveResolverBatchRecordSource);
493
+ }
494
+
495
+ // Reset batched state.
496
+ this._liveResolverBatchRecordSource = null;
497
+ this._handlingBatch = false;
498
+ return shouldPublish;
499
+ }
500
+ }
501
+
477
502
  _setLiveResolverValue(
478
503
  resolverRecord: Record,
479
- liveValue: LiveState<mixed>,
504
+ liveValue: LiveState<unknown>,
480
505
  field: ReaderRelayResolver | ReaderRelayLiveResolver,
481
506
  variables: Variables,
482
507
  ): DataIDSet | null {
483
- let value: null | mixed = null;
484
- let resolverError: null | mixed = null;
508
+ let value: null | unknown = null;
509
+ let resolverError: null | unknown = null;
485
510
  try {
486
511
  value = liveValue.read();
487
512
  } catch (e) {
@@ -498,7 +523,7 @@ class LiveResolverCache implements ResolverCache {
498
523
 
499
524
  _setResolverValue(
500
525
  resolverRecord: Record,
501
- value: mixed,
526
+ value: unknown,
502
527
  field: ReaderRelayResolver | ReaderRelayLiveResolver,
503
528
  variables: Variables,
504
529
  ): DataIDSet | null {
@@ -623,13 +648,23 @@ class LiveResolverCache implements ResolverCache {
623
648
  );
624
649
  } else {
625
650
  shallowFreeze(value);
626
- // For "classic" resolvers (or if the value is nullish), we are just setting their
627
- // value as is.
651
+
652
+ // For "classic" resolvers (or if the value is nullish/suspense), we are
653
+ // set their value...
628
654
  RelayModernRecord.setValue(
629
655
  resolverRecord,
630
656
  RELAY_RESOLVER_VALUE_KEY,
631
657
  value,
632
658
  );
659
+
660
+ // ...and clear the output type record IDs, if any since a resolver must
661
+ // be an output type resolver with a non-suspended, non-null value to
662
+ // refernce any output type record ids.
663
+ RelayModernRecord.setValue(
664
+ resolverRecord,
665
+ RELAY_RESOLVER_OUTPUT_TYPE_RECORD_IDS,
666
+ new Set(),
667
+ );
633
668
  }
634
669
 
635
670
  return updatedDataIDs;
@@ -639,7 +674,7 @@ class LiveResolverCache implements ResolverCache {
639
674
  this._store.__notifyUpdatedSubscribers(updatedDataIDs);
640
675
  }
641
676
 
642
- _getResolverValue(resolverRecord: Record): mixed {
677
+ _getResolverValue(resolverRecord: Record): unknown {
643
678
  return RelayModernRecord.getValue(resolverRecord, RELAY_RESOLVER_VALUE_KEY);
644
679
  }
645
680
 
@@ -659,9 +694,9 @@ class LiveResolverCache implements ResolverCache {
659
694
  const recordID: string = recordsToVisit.pop();
660
695
  visited.add(recordID);
661
696
 
662
- // $FlowFixMe[incompatible-call]
697
+ // $FlowFixMe[incompatible-type]
663
698
  updatedDataIDs.add(recordID);
664
- // $FlowFixMe[incompatible-call]
699
+ // $FlowFixMe[incompatible-type]
665
700
  const fragmentSet = this._recordIDToResolverIDs.get(recordID);
666
701
  if (fragmentSet == null) {
667
702
  continue;
@@ -737,7 +772,7 @@ class LiveResolverCache implements ResolverCache {
737
772
  // containing only "weak" records.
738
773
  _normalizeOutputTypeValue(
739
774
  outputTypeDataID: DataID,
740
- value: {+[key: string]: mixed},
775
+ value: {+[key: string]: unknown},
741
776
  variables: Variables,
742
777
  normalizationInfo: ResolverNormalizationInfo,
743
778
  fieldPath: Array<string>,
@@ -788,7 +823,7 @@ class LiveResolverCache implements ResolverCache {
788
823
  return source;
789
824
  }
790
825
  default:
791
- (normalizationInfo.kind: empty);
826
+ normalizationInfo.kind as empty;
792
827
  invariant(
793
828
  false,
794
829
  'LiveResolverCache: Unexpected normalization info kind `%s`.',
@@ -846,7 +881,7 @@ class LiveResolverCache implements ResolverCache {
846
881
  function updateCurrentSource(
847
882
  currentSource: MutableRecordSource,
848
883
  nextSource: RecordSource,
849
- prevOutputTypeRecordIDs: ?$ReadOnlySet<DataID>,
884
+ prevOutputTypeRecordIDs: ?ReadonlySet<DataID>,
850
885
  ): DataIDSet {
851
886
  const updatedDataIDs = new Set<DataID>();
852
887
 
@@ -944,7 +979,7 @@ function markInvalidatedLinkedResolverRecords(
944
979
 
945
980
  function unsubscribeFromLiveResolverRecordsImpl(
946
981
  recordSource: RecordSource,
947
- invalidatedDataIDs: $ReadOnlySet<DataID>,
982
+ invalidatedDataIDs: ReadonlySet<DataID>,
948
983
  ): void {
949
984
  if (invalidatedDataIDs.size === 0) {
950
985
  return;
@@ -999,7 +1034,7 @@ function getConcreteTypename(
999
1034
  const typename =
1000
1035
  normalizationInfo.concreteType ??
1001
1036
  // $FlowFixMe[prop-missing]
1002
- (currentValue.__typename: string);
1037
+ (currentValue.__typename as string);
1003
1038
  invariant(
1004
1039
  typename != null,
1005
1040
  'normalizationInfo.concreteType should not be null, or the value returned from the resolver should include a __typename field, ' +
@@ -1010,6 +1045,6 @@ function getConcreteTypename(
1010
1045
 
1011
1046
  module.exports = {
1012
1047
  LiveResolverCache,
1013
- getUpdatedDataIDs,
1014
1048
  RELAY_RESOLVER_LIVE_STATE_SUBSCRIPTION_KEY,
1049
+ getUpdatedDataIDs,
1015
1050
  };
@@ -11,16 +11,16 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- const LIVE_RESOLVER_SUSPENSE_SENTINEL: mixed = Object.freeze({
14
+ const LIVE_RESOLVER_SUSPENSE_SENTINEL: unknown = Object.freeze({
15
15
  __LIVE_RESOLVER_SUSPENSE_SENTINEL: true,
16
16
  });
17
17
 
18
18
  function suspenseSentinel(): empty {
19
- // $FlowFixMe[incompatible-return]
19
+ // $FlowFixMe[incompatible-type]
20
20
  return LIVE_RESOLVER_SUSPENSE_SENTINEL;
21
21
  }
22
22
 
23
- function isSuspenseSentinel(value: mixed): boolean {
23
+ function isSuspenseSentinel(value: unknown): boolean {
24
24
  return value === LIVE_RESOLVER_SUSPENSE_SENTINEL;
25
25
  }
26
26
 
@@ -18,7 +18,7 @@ const RelayModernRecord = require('../RelayModernRecord');
18
18
  const {RELAY_RESOLVER_OUTPUT_TYPE_RECORD_IDS} = require('../RelayStoreUtils');
19
19
  const invariant = require('invariant');
20
20
 
21
- function getOutputTypeRecordIDs(record: Record): $ReadOnlySet<DataID> | null {
21
+ function getOutputTypeRecordIDs(record: Record): ReadonlySet<DataID> | null {
22
22
  const maybeOutputTypeRecordIDs = RelayModernRecord.getValue(
23
23
  record,
24
24
  RELAY_RESOLVER_OUTPUT_TYPE_RECORD_IDS,
@@ -13,9 +13,9 @@
13
13
 
14
14
  import type {LiveState} from '../RelayStoreTypes';
15
15
 
16
- declare function isLiveStateValue<T, U = LiveState<T>>(v: mixed): v is U;
16
+ declare function isLiveStateValue<T, U = LiveState<T>>(v: unknown): v is U;
17
17
 
18
- function isLiveStateValue(v: mixed) {
18
+ function isLiveStateValue(v: unknown) {
19
19
  return (
20
20
  v != null &&
21
21
  typeof v === 'object' &&
@@ -17,7 +17,7 @@ import type {FragmentType, ResolverContext} from '../RelayStoreTypes';
17
17
  const {readFragment} = require('../ResolverFragments');
18
18
  const invariant = require('invariant');
19
19
 
20
- type ResolverFn = ($FlowFixMe, ?$FlowFixMe, ResolverContext) => mixed;
20
+ type ResolverFn = ($FlowFixMe, ?$FlowFixMe, ResolverContext) => unknown;
21
21
 
22
22
  /**
23
23
  *
@@ -31,20 +31,23 @@ type ResolverFn = ($FlowFixMe, ?$FlowFixMe, ResolverContext) => mixed;
31
31
  * This will not call the `resolverFn` if the fragment data for it is null/undefined.
32
32
  * The the compiler generates calls to this function, ensuring the correct set of arguments.
33
33
  */
34
- function resolverDataInjector<TFragmentType: FragmentType, TData: ?{...}>(
34
+ function resolverDataInjector<
35
+ TFragmentType extends FragmentType,
36
+ TData extends ?{...},
37
+ >(
35
38
  fragment: Fragment<TFragmentType, TData>,
36
39
  // Resolvers have their own type assertions, we don't want to confuse users
37
40
  // with a type error in their generated code at this point.
38
41
  _resolverFn: $FlowFixMe,
39
42
  fieldName?: string,
40
43
  isRequiredField?: boolean,
41
- ): (fragmentKey: TFragmentType, args: mixed) => mixed {
44
+ ): (fragmentKey: TFragmentType, args: unknown) => unknown {
42
45
  const resolverFn: ResolverFn = _resolverFn;
43
46
  return (
44
47
  fragmentKey: TFragmentType,
45
- args: mixed,
48
+ args: unknown,
46
49
  resolverContext: ResolverContext,
47
- ): mixed => {
50
+ ): unknown => {
48
51
  const data = readFragment(fragment, fragmentKey);
49
52
  if (fieldName != null) {
50
53
  if (data == null) {
@@ -9,7 +9,11 @@
9
9
  * @oncall relay
10
10
  */
11
11
 
12
- import type {PluralReaderSelector, RequestDescriptor} from './RelayStoreTypes';
12
+ import type {
13
+ PluralReaderSelector,
14
+ ReaderSelector,
15
+ RequestDescriptor,
16
+ } from './RelayStoreTypes';
13
17
  import type {
14
18
  Fragment,
15
19
  FragmentType,
@@ -59,12 +63,12 @@ export type HasSpread<TFragmentType> = {
59
63
  * you might choose to @defer a fragment that you only need to access inside an
60
64
  * event handler and then await its value inside the handler if/when it is triggered.
61
65
  */
62
- async function waitForFragmentData<TFragmentType: FragmentType, TData>(
66
+ async function waitForFragmentData<TFragmentType extends FragmentType, TData>(
63
67
  environment: IEnvironment,
64
68
  fragment: Fragment<TFragmentType, TData>,
65
69
  fragmentRef:
66
70
  | HasSpread<TFragmentType>
67
- | $ReadOnlyArray<HasSpread<TFragmentType>>,
71
+ | ReadonlyArray<HasSpread<TFragmentType>>,
68
72
  ): Promise<TData> {
69
73
  let subscription: ?Subscription;
70
74
 
@@ -86,18 +90,18 @@ async function waitForFragmentData<TFragmentType: FragmentType, TData>(
86
90
  });
87
91
  subscription?.unsubscribe();
88
92
  return data;
89
- } catch (e: mixed) {
93
+ } catch (e: unknown) {
90
94
  subscription?.unsubscribe();
91
95
  throw e;
92
96
  }
93
97
  }
94
98
 
95
- declare function observeFragment<TFragmentType: FragmentType, TData>(
99
+ declare function observeFragment<TFragmentType extends FragmentType, TData>(
96
100
  environment: IEnvironment,
97
101
  fragment: Fragment<TFragmentType, TData>,
98
102
  fragmentRef:
99
103
  | HasSpread<TFragmentType>
100
- | $ReadOnlyArray<HasSpread<TFragmentType>>,
104
+ | ReadonlyArray<HasSpread<TFragmentType>>,
101
105
  ): Observable<FragmentState<TData>>;
102
106
 
103
107
  /**
@@ -112,25 +116,28 @@ declare function observeFragment<TFragmentType: FragmentType, TData>(
112
116
  * a field error due to @required(action: THROW) or @throwOnFieldError
113
117
  * - 'loading': The fragment is still in flight and is still expected to resolver.
114
118
  */
115
- function observeFragment<TFragmentType: FragmentType, TData>(
119
+ function observeFragment<TFragmentType extends FragmentType, TData>(
116
120
  environment: IEnvironment,
117
121
  fragment: Fragment<TFragmentType, TData>,
118
- fragmentRef: mixed,
119
- ): mixed {
122
+ fragmentRef: unknown,
123
+ ): unknown {
120
124
  const fragmentNode = getFragment(fragment);
121
125
  const fragmentSelector = getSelector(fragmentNode, fragmentRef);
126
+
127
+ invariant(fragmentSelector != null, 'Expected a selector, got null.');
128
+
122
129
  invariant(
123
- fragmentNode.metadata?.hasClientEdges == null,
130
+ fragmentNode.metadata?.hasClientEdges == null ||
131
+ fragmentSelectorUsesExecTimeResolver(fragmentSelector),
124
132
  "Client edges aren't supported yet.",
125
133
  );
126
- invariant(fragmentSelector != null, 'Expected a selector, got null.');
127
134
  switch (fragmentSelector.kind) {
128
135
  case 'SingularReaderSelector':
129
136
  return observeSingularSelector(environment, fragment, fragmentSelector);
130
137
  case 'PluralReaderSelector': {
131
138
  return observePluralSelector(
132
139
  environment,
133
- (fragment: $FlowFixMe),
140
+ fragment as $FlowFixMe,
134
141
  fragmentSelector,
135
142
  );
136
143
  }
@@ -138,7 +145,29 @@ function observeFragment<TFragmentType: FragmentType, TData>(
138
145
  invariant(false, 'Unsupported fragment selector kind');
139
146
  }
140
147
 
141
- function observeSingularSelector<TFragmentType: FragmentType, TData>(
148
+ function fragmentSelectorUsesExecTimeResolver(
149
+ fragmentSelector: ReaderSelector,
150
+ ) {
151
+ switch (fragmentSelector?.kind) {
152
+ case 'SingularReaderSelector':
153
+ return (
154
+ (fragmentSelector.owner.node.operation?.use_exec_time_resolvers ??
155
+ fragmentSelector.owner.node.operation?.exec_time_resolvers_enabled_provider?.get()) ===
156
+ true
157
+ );
158
+ case 'PluralReaderSelector': {
159
+ return fragmentSelector.selectors?.every(
160
+ selector =>
161
+ (selector.owner.node.operation.use_exec_time_resolvers ??
162
+ selector.owner.node.operation?.exec_time_resolvers_enabled_provider?.get()) ===
163
+ true,
164
+ );
165
+ }
166
+ }
167
+ return false;
168
+ }
169
+
170
+ function observeSingularSelector<TFragmentType extends FragmentType, TData>(
142
171
  environment: IEnvironment,
143
172
  fragmentNode: Fragment<TFragmentType, TData>,
144
173
  fragmentSelector: SingularReaderSelector,
@@ -171,8 +200,8 @@ function observeSingularSelector<TFragmentType: FragmentType, TData>(
171
200
  }
172
201
 
173
202
  function observePluralSelector<
174
- TFragmentType: FragmentType,
175
- TData: Array<mixed>,
203
+ TFragmentType extends FragmentType,
204
+ TData extends Array<unknown>,
176
205
  >(
177
206
  environment: IEnvironment,
178
207
  fragmentNode: Fragment<TFragmentType, TData>,
@@ -193,7 +222,7 @@ function observePluralSelector<
193
222
  ),
194
223
  );
195
224
 
196
- sink.next((mergeFragmentStates(states): $FlowFixMe));
225
+ sink.next(mergeFragmentStates(states) as $FlowFixMe);
197
226
 
198
227
  const subscriptions = snapshots.map((snapshot, index) =>
199
228
  environment.subscribe(snapshot, latestSnapshot => {
@@ -205,7 +234,7 @@ function observePluralSelector<
205
234
  );
206
235
  // This doesn't batch updates, so it will notify the subscriber multiple times
207
236
  // if a store update impacting multiple items in the list is published.
208
- sink.next((mergeFragmentStates(states): $FlowFixMe));
237
+ sink.next(mergeFragmentStates(states) as $FlowFixMe);
209
238
  }),
210
239
  );
211
240
 
@@ -213,7 +242,7 @@ function observePluralSelector<
213
242
  });
214
243
  }
215
244
 
216
- function snapshotToFragmentState<TFragmentType: FragmentType, TData>(
245
+ function snapshotToFragmentState<TFragmentType extends FragmentType, TData>(
217
246
  environment: IEnvironment,
218
247
  fragmentNode: Fragment<TFragmentType, TData>,
219
248
  owner: RequestDescriptor,
@@ -266,11 +295,11 @@ function snapshotToFragmentState<TFragmentType: FragmentType, TData>(
266
295
 
267
296
  invariant(snapshot.data != null, 'Expected data to be non-null.');
268
297
 
269
- return {state: 'ok', value: (snapshot.data: $FlowFixMe)};
298
+ return {state: 'ok', value: snapshot.data as $FlowFixMe};
270
299
  }
271
300
 
272
301
  function mergeFragmentStates<T>(
273
- states: $ReadOnlyArray<FragmentState<T>>,
302
+ states: ReadonlyArray<FragmentState<T>>,
274
303
  ): FragmentState<Array<T>> {
275
304
  const value = [];
276
305
  for (const state of states) {