relay-runtime 0.0.0-main-dbe0cbb6 → 0.0.0-main-9e60e09f

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.
@@ -109,6 +109,7 @@ class RelayReader {
109
109
  _selector: SingularReaderSelector;
110
110
  _variables: Variables;
111
111
  _resolverCache: ResolverCache;
112
+ _fragmentName: string;
112
113
 
113
114
  constructor(
114
115
  recordSource: RecordSource,
@@ -130,6 +131,7 @@ class RelayReader {
130
131
  this._selector = selector;
131
132
  this._variables = selector.variables;
132
133
  this._resolverCache = resolverCache;
134
+ this._fragmentName = selector.node.name;
133
135
  }
134
136
 
135
137
  read(): Snapshot {
@@ -267,7 +269,7 @@ class RelayReader {
267
269
  // encounter is likely to be the root cause of the error.
268
270
  return;
269
271
  }
270
- const owner = this._selector.node.name;
272
+ const owner = this._fragmentName;
271
273
 
272
274
  switch (action) {
273
275
  case 'THROW':
@@ -275,9 +277,19 @@ class RelayReader {
275
277
  return;
276
278
  case 'LOG':
277
279
  if (this._missingRequiredFields == null) {
278
- this._missingRequiredFields = {action, fields: []};
280
+ this._missingRequiredFields = {
281
+ action,
282
+ fields: [{path: fieldPath, owner}],
283
+ };
284
+ } else {
285
+ this._missingRequiredFields = {
286
+ action,
287
+ fields: [
288
+ ...this._missingRequiredFields.fields,
289
+ {path: fieldPath, owner},
290
+ ],
291
+ };
279
292
  }
280
- this._missingRequiredFields.fields.push({path: fieldPath, owner});
281
293
  return;
282
294
  default:
283
295
  (action: empty);
@@ -511,6 +523,8 @@ class RelayReader {
511
523
  // inputs have changed since a previous evaluation:
512
524
  let fragmentValue;
513
525
  let fragmentReaderSelector;
526
+ let fragmentMissingRequiredFields: ?MissingRequiredFields;
527
+ let previousMissingRequriedFields: ?MissingRequiredFields;
514
528
  const fragmentSeenRecordIDs = new Set();
515
529
 
516
530
  const getDataForResolverFragment = singularReaderSelector => {
@@ -525,11 +539,14 @@ class RelayReader {
525
539
  try {
526
540
  this._seenRecords = fragmentSeenRecordIDs;
527
541
  const resolverFragmentData = {};
542
+ previousMissingRequriedFields = this._missingRequiredFields;
543
+ this._missingRequiredFields = null;
528
544
  this._createInlineDataOrResolverFragmentPointer(
529
545
  singularReaderSelector.node,
530
546
  record,
531
547
  resolverFragmentData,
532
548
  );
549
+ fragmentMissingRequiredFields = this._missingRequiredFields;
533
550
  fragmentValue = resolverFragmentData[FRAGMENTS_KEY]?.[fragment.name];
534
551
  invariant(
535
552
  typeof fragmentValue === 'object' && fragmentValue !== null,
@@ -538,36 +555,43 @@ class RelayReader {
538
555
  return fragmentValue;
539
556
  } finally {
540
557
  this._seenRecords = existingSeenRecords;
558
+ this._missingRequiredFields = previousMissingRequriedFields;
541
559
  }
542
560
  };
543
561
  const resolverContext = {getDataForResolverFragment};
544
562
 
545
- const [result, seenRecord] = this._resolverCache.readFromCacheOrEvaluate(
546
- record,
547
- field,
548
- this._variables,
549
- () => {
550
- const key = {
551
- __id: RelayModernRecord.getDataID(record),
552
- __fragmentOwner: this._owner,
553
- __fragments: {
554
- [fragment.name]: {}, // Arguments to this fragment; not yet supported.
555
- },
556
- };
557
- return withResolverContext(resolverContext, () => {
558
- // $FlowFixMe[prop-missing] - resolver module's type signature is a lie
559
- const resolverResult = resolverModule(key);
560
- return {
561
- resolverResult,
562
- fragmentValue,
563
- resolverID,
564
- seenRecordIDs: fragmentSeenRecordIDs,
565
- readerSelector: fragmentReaderSelector,
563
+ const [result, seenRecord, missingRequiredFields] =
564
+ this._resolverCache.readFromCacheOrEvaluate(
565
+ record,
566
+ field,
567
+ this._variables,
568
+ () => {
569
+ const key = {
570
+ __id: RelayModernRecord.getDataID(record),
571
+ __fragmentOwner: this._owner,
572
+ __fragments: {
573
+ [fragment.name]: {}, // Arguments to this fragment; not yet supported.
574
+ },
566
575
  };
567
- });
568
- },
569
- getDataForResolverFragment,
570
- );
576
+ return withResolverContext(resolverContext, () => {
577
+ // $FlowFixMe[prop-missing] - resolver module's type signature is a lie
578
+ const resolverResult = resolverModule(key);
579
+ return {
580
+ resolverResult,
581
+ fragmentValue,
582
+ resolverID,
583
+ seenRecordIDs: fragmentSeenRecordIDs,
584
+ readerSelector: fragmentReaderSelector,
585
+ missingRequiredFields: fragmentMissingRequiredFields,
586
+ };
587
+ });
588
+ },
589
+ getDataForResolverFragment,
590
+ );
591
+
592
+ if (missingRequiredFields != null) {
593
+ this._addMissingRequiredFields(missingRequiredFields);
594
+ }
571
595
  if (seenRecord != null) {
572
596
  this._seenRecords.add(seenRecord);
573
597
  }
@@ -896,14 +920,37 @@ class RelayReader {
896
920
  data[ID_KEY] = RelayModernRecord.getDataID(record);
897
921
  }
898
922
  const inlineData = {};
923
+ const parentFragmentName = this._fragmentName;
924
+ this._fragmentName = fragmentSpreadOrFragment.name;
899
925
  this._traverseSelections(
900
926
  fragmentSpreadOrFragment.selections,
901
927
  record,
902
928
  inlineData,
903
929
  );
930
+ this._fragmentName = parentFragmentName;
904
931
  // $FlowFixMe[cannot-write] - writing into read-only field
905
932
  fragmentPointers[fragmentSpreadOrFragment.name] = inlineData;
906
933
  }
934
+
935
+ _addMissingRequiredFields(additional: MissingRequiredFields) {
936
+ if (this._missingRequiredFields == null) {
937
+ this._missingRequiredFields = additional;
938
+ return;
939
+ }
940
+
941
+ if (this._missingRequiredFields.action === 'THROW') {
942
+ return;
943
+ }
944
+ if (additional.action === 'THROW') {
945
+ this._missingRequiredFields = additional;
946
+ return;
947
+ }
948
+
949
+ this._missingRequiredFields = {
950
+ action: 'LOG',
951
+ fields: [...this._missingRequiredFields.fields, ...additional.fields],
952
+ };
953
+ }
907
954
  }
908
955
 
909
956
  module.exports = {read};
@@ -117,9 +117,10 @@ type MissingRequiredField = {|
117
117
  owner: string,
118
118
  |};
119
119
 
120
- export type MissingRequiredFields =
120
+ export type MissingRequiredFields = $ReadOnly<
121
121
  | {|action: 'THROW', field: MissingRequiredField|}
122
- | {|action: 'LOG', fields: Array<MissingRequiredField>|};
122
+ | {|action: 'LOG', fields: Array<MissingRequiredField>|},
123
+ >;
123
124
 
124
125
  export type ClientEdgeTraversalInfo = {|
125
126
  +readerClientEdge: ReaderClientEdge,
@@ -219,6 +219,7 @@ const RelayStoreUtils = {
219
219
  RELAY_RESOLVER_INVALIDATION_KEY: '__resolverValueMayBeInvalid',
220
220
  RELAY_RESOLVER_INPUTS_KEY: '__resolverInputValues',
221
221
  RELAY_RESOLVER_READER_SELECTOR_KEY: '__resolverReaderSelector',
222
+ RELAY_RESOLVER_MISSING_REQUIRED_FIELDS_KEY: '__resolverMissingRequiredFields',
222
223
 
223
224
  formatStorageKey,
224
225
  getArgumentValue,
@@ -15,6 +15,7 @@
15
15
  import type {ReaderRelayResolver} from '../util/ReaderNode';
16
16
  import type {DataID, Variables} from '../util/RelayRuntimeTypes';
17
17
  import type {
18
+ MissingRequiredFields,
18
19
  MutableRecordSource,
19
20
  Record,
20
21
  SingularReaderSelector,
@@ -26,6 +27,7 @@ const RelayModernRecord = require('./RelayModernRecord');
26
27
  const {
27
28
  RELAY_RESOLVER_INPUTS_KEY,
28
29
  RELAY_RESOLVER_INVALIDATION_KEY,
30
+ RELAY_RESOLVER_MISSING_REQUIRED_FIELDS_KEY,
29
31
  RELAY_RESOLVER_READER_SELECTOR_KEY,
30
32
  RELAY_RESOLVER_VALUE_KEY,
31
33
  getStorageKey,
@@ -40,6 +42,7 @@ type EvaluationResult<T> = {|
40
42
  resolverID: ResolverID,
41
43
  seenRecordIDs: Set<DataID>,
42
44
  readerSelector: SingularReaderSelector,
45
+ missingRequiredFields: ?MissingRequiredFields,
43
46
  |};
44
47
 
45
48
  export interface ResolverCache {
@@ -49,7 +52,7 @@ export interface ResolverCache {
49
52
  variables: Variables,
50
53
  evaluate: () => EvaluationResult<T>,
51
54
  getDataForResolverFragment: (SingularReaderSelector) => mixed,
52
- ): [T /* Answer */, ?DataID /* Seen record */];
55
+ ): [T /* Answer */, ?DataID /* Seen record */, ?MissingRequiredFields];
53
56
  invalidateDataIDs(
54
57
  updatedDataIDs: Set<DataID>, // Mutated in place
55
58
  ): void;
@@ -65,8 +68,9 @@ class NoopResolverCache implements ResolverCache {
65
68
  variables: Variables,
66
69
  evaluate: () => EvaluationResult<T>,
67
70
  getDataForResolverFragment: SingularReaderSelector => mixed,
68
- ): [T /* Answer */, ?DataID /* Seen record */] {
69
- return [evaluate().resolverResult, undefined];
71
+ ): [T /* Answer */, ?DataID /* Seen record */, ?MissingRequiredFields] {
72
+ const {resolverResult, missingRequiredFields} = evaluate();
73
+ return [resolverResult, undefined, missingRequiredFields];
70
74
  }
71
75
  invalidateDataIDs(updatedDataIDs: Set<DataID>): void {}
72
76
  }
@@ -102,7 +106,7 @@ class RecordResolverCache implements ResolverCache {
102
106
  variables: Variables,
103
107
  evaluate: () => EvaluationResult<T>,
104
108
  getDataForResolverFragment: SingularReaderSelector => mixed,
105
- ): [T /* Answer */, ?DataID /* Seen record */] {
109
+ ): [T /* Answer */, ?DataID /* Seen record */, ?MissingRequiredFields] {
106
110
  const recordSource = this._getRecordSource();
107
111
  const recordID = RelayModernRecord.getDataID(record);
108
112
 
@@ -133,6 +137,11 @@ class RecordResolverCache implements ResolverCache {
133
137
  RELAY_RESOLVER_READER_SELECTOR_KEY,
134
138
  evaluationResult.readerSelector,
135
139
  );
140
+ RelayModernRecord.setValue(
141
+ linkedRecord,
142
+ RELAY_RESOLVER_MISSING_REQUIRED_FIELDS_KEY,
143
+ evaluationResult.missingRequiredFields,
144
+ );
136
145
  recordSource.set(linkedID, linkedRecord);
137
146
 
138
147
  // Link the resolver value record to the resolver field of the record being read:
@@ -155,7 +164,11 @@ class RecordResolverCache implements ResolverCache {
155
164
 
156
165
  // $FlowFixMe[incompatible-type] - will always be empty
157
166
  const answer: T = linkedRecord[RELAY_RESOLVER_VALUE_KEY];
158
- return [answer, linkedID];
167
+
168
+ const missingRequiredFields: ?MissingRequiredFields =
169
+ // $FlowFixMe[incompatible-type] - casting mixed
170
+ linkedRecord[RELAY_RESOLVER_MISSING_REQUIRED_FIELDS_KEY];
171
+ return [answer, linkedID, missingRequiredFields];
159
172
  }
160
173
 
161
174
  invalidateDataIDs(
@@ -35,7 +35,7 @@ export type NormalizationRootNode =
35
35
  | ConcreteRequest
36
36
  | NormalizationSplitOperation;
37
37
 
38
- export type ProvidedVariablesType = {[key: string]: {|get(): mixed|}};
38
+ export type ProvidedVariablesType = {+[key: string]: {|get(): mixed|}};
39
39
 
40
40
  /**
41
41
  * Contains the parameters required for executing a GraphQL request.