relay-runtime 2.0.0-rc.2 → 5.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 (77) hide show
  1. package/index.js +1 -1
  2. package/lib/{generateRelayClientID.js → ClientID.js} +10 -3
  3. package/lib/ConvertToExecuteFunction.js +6 -4
  4. package/lib/DataChecker.js +88 -69
  5. package/lib/NormalizationNode.js +1 -1
  6. package/lib/ReaderNode.js +1 -1
  7. package/lib/RelayCombinedEnvironmentTypes.js +1 -1
  8. package/lib/RelayConcreteNode.js +5 -2
  9. package/lib/RelayConcreteVariables.js +15 -9
  10. package/lib/RelayConnectionHandler.js +27 -20
  11. package/lib/RelayConnectionInterface.js +4 -2
  12. package/lib/RelayCore.js +48 -15
  13. package/lib/RelayDeclarativeMutationConfig.js +16 -15
  14. package/lib/RelayDefaultHandleKey.js +1 -1
  15. package/lib/RelayDefaultHandlerProvider.js +7 -6
  16. package/lib/RelayDefaultMissingFieldHandlers.js +26 -0
  17. package/lib/RelayError.js +7 -2
  18. package/lib/RelayFeatureFlags.js +16 -0
  19. package/lib/RelayInMemoryRecordSource.js +8 -2
  20. package/lib/RelayModernEnvironment.js +159 -237
  21. package/lib/RelayModernFragmentOwner.js +72 -0
  22. package/lib/RelayModernFragmentSpecResolver.js +66 -15
  23. package/lib/RelayModernGraphQLTag.js +9 -5
  24. package/lib/RelayModernOperationDescriptor.js +9 -6
  25. package/lib/RelayModernQueryExecutor.js +791 -0
  26. package/lib/RelayModernRecord.js +44 -24
  27. package/lib/RelayModernSelector.js +208 -82
  28. package/lib/RelayModernStore.js +66 -34
  29. package/lib/RelayNetwork.js +14 -7
  30. package/lib/RelayNetworkLogger.js +6 -2
  31. package/lib/RelayNetworkLoggerTransaction.js +8 -4
  32. package/lib/RelayNetworkTypes.js +1 -1
  33. package/lib/RelayObservable.js +72 -41
  34. package/lib/RelayOperationTracker.js +265 -0
  35. package/lib/RelayProfiler.js +10 -6
  36. package/lib/RelayPublishQueue.js +66 -47
  37. package/lib/RelayQueryResponseCache.js +11 -5
  38. package/lib/RelayReader.js +135 -126
  39. package/lib/RelayRecordProxy.js +24 -20
  40. package/lib/RelayRecordSourceMutator.js +88 -25
  41. package/lib/RelayRecordSourceProxy.js +38 -19
  42. package/lib/RelayRecordSourceSelectorProxy.js +10 -7
  43. package/lib/RelayRecordState.js +1 -1
  44. package/lib/RelayReferenceMarker.js +66 -55
  45. package/lib/RelayReplaySubject.js +134 -0
  46. package/lib/RelayResponseNormalizer.js +245 -134
  47. package/lib/RelayRuntimeTypes.js +1 -1
  48. package/lib/RelayStoreUtils.js +55 -16
  49. package/lib/RelayViewerHandler.js +8 -50
  50. package/lib/StoreInspector.js +171 -0
  51. package/lib/applyRelayModernOptimisticMutation.js +8 -2
  52. package/lib/cloneRelayHandleSourceField.js +17 -7
  53. package/lib/commitLocalUpdate.js +1 -1
  54. package/lib/commitRelayModernMutation.js +33 -13
  55. package/lib/createRelayContext.js +27 -0
  56. package/lib/createRelayNetworkLogger.js +8 -2
  57. package/lib/deepFreeze.js +1 -1
  58. package/lib/defaultGetDataID.js +24 -0
  59. package/lib/fetchQueryInternal.js +232 -0
  60. package/lib/fetchRelayModernQuery.js +5 -3
  61. package/lib/getFragmentIdentifier.js +52 -0
  62. package/lib/getFragmentSpecIdentifier.js +26 -0
  63. package/lib/getRelayHandleKey.js +8 -2
  64. package/lib/getRequestParametersIdentifier.js +26 -0
  65. package/lib/hasOverlappingIDs.js +1 -1
  66. package/lib/index.js +155 -53
  67. package/lib/isPromise.js +1 -1
  68. package/lib/isScalarAndEqual.js +1 -1
  69. package/lib/normalizeRelayPayload.js +19 -10
  70. package/lib/recycleNodesInto.js +23 -5
  71. package/lib/requestRelaySubscription.js +9 -3
  72. package/lib/validateMutation.js +13 -6
  73. package/package.json +2 -2
  74. package/relay-runtime.js +2 -2
  75. package/relay-runtime.min.js +2 -2
  76. package/lib/normalizePayload.js +0 -37
  77. package/lib/simpleClone.js +0 -27
@@ -9,7 +9,27 @@
9
9
  */
10
10
  'use strict';
11
11
 
12
- var _objectSpread2 = require("@babel/runtime/helpers/interopRequireDefault")(require("@babel/runtime/helpers/objectSpread"));
12
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
13
+
14
+ var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));
15
+
16
+ var areEqual = require("fbjs/lib/areEqual");
17
+
18
+ var deepFreeze = require("./deepFreeze");
19
+
20
+ var invariant = require("fbjs/lib/invariant");
21
+
22
+ var warning = require("fbjs/lib/warning");
23
+
24
+ var _require = require("./ClientID"),
25
+ isClientID = _require.isClientID;
26
+
27
+ var _require2 = require("./RelayStoreUtils"),
28
+ ID_KEY = _require2.ID_KEY,
29
+ REF_KEY = _require2.REF_KEY,
30
+ REFS_KEY = _require2.REFS_KEY,
31
+ TYPENAME_KEY = _require2.TYPENAME_KEY,
32
+ UNPUBLISH_FIELD_SENTINEL = _require2.UNPUBLISH_FIELD_SENTINEL;
13
33
 
14
34
  /**
15
35
  * @public
@@ -78,7 +98,7 @@ function clone(record) {
78
98
  function copyFields(source, sink) {
79
99
  for (var key in source) {
80
100
  if (source.hasOwnProperty(key)) {
81
- if (key !== require("./RelayStoreUtils").ID_KEY && key !== require("./RelayStoreUtils").TYPENAME_KEY) {
101
+ if (key !== ID_KEY && key !== TYPENAME_KEY) {
82
102
  sink[key] = source[key];
83
103
  }
84
104
  }
@@ -94,8 +114,8 @@ function copyFields(source, sink) {
94
114
  function create(dataID, typeName) {
95
115
  // See perf note above for why we aren't using computed property access.
96
116
  var record = {};
97
- record[require("./RelayStoreUtils").ID_KEY] = dataID;
98
- record[require("./RelayStoreUtils").TYPENAME_KEY] = typeName;
117
+ record[ID_KEY] = dataID;
118
+ record[TYPENAME_KEY] = typeName;
99
119
  return record;
100
120
  }
101
121
  /**
@@ -106,7 +126,7 @@ function create(dataID, typeName) {
106
126
 
107
127
 
108
128
  function getDataID(record) {
109
- return record[require("./RelayStoreUtils").ID_KEY];
129
+ return record[ID_KEY];
110
130
  }
111
131
  /**
112
132
  * @public
@@ -116,7 +136,7 @@ function getDataID(record) {
116
136
 
117
137
 
118
138
  function getType(record) {
119
- return record[require("./RelayStoreUtils").TYPENAME_KEY];
139
+ return record[TYPENAME_KEY];
120
140
  }
121
141
  /**
122
142
  * @public
@@ -129,7 +149,7 @@ function getValue(record, storageKey) {
129
149
  var value = record[storageKey];
130
150
 
131
151
  if (value && typeof value === 'object') {
132
- !(!value.hasOwnProperty(require("./RelayStoreUtils").REF_KEY) && !value.hasOwnProperty(require("./RelayStoreUtils").REFS_KEY)) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernRecord.getValue(): Expected a scalar (non-link) value for `%s.%s` ' + 'but found %s.', record[require("./RelayStoreUtils").ID_KEY], storageKey, value.hasOwnProperty(require("./RelayStoreUtils").REF_KEY) ? 'a linked record' : 'plural linked records') : require("fbjs/lib/invariant")(false) : void 0;
152
+ !(!value.hasOwnProperty(REF_KEY) && !value.hasOwnProperty(REFS_KEY)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernRecord.getValue(): Expected a scalar (non-link) value for `%s.%s` ' + 'but found %s.', record[ID_KEY], storageKey, value.hasOwnProperty(REF_KEY) ? 'a linked record' : 'plural linked records') : invariant(false) : void 0;
133
153
  }
134
154
 
135
155
  return value;
@@ -149,8 +169,8 @@ function getLinkedRecordID(record, storageKey) {
149
169
  return link;
150
170
  }
151
171
 
152
- !(typeof link === 'object' && link && typeof link[require("./RelayStoreUtils").REF_KEY] === 'string') ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernRecord.getLinkedRecordID(): Expected `%s.%s` to be a linked ID, ' + 'was `%s`.', record[require("./RelayStoreUtils").ID_KEY], storageKey, JSON.stringify(link)) : require("fbjs/lib/invariant")(false) : void 0;
153
- return link[require("./RelayStoreUtils").REF_KEY];
172
+ !(typeof link === 'object' && link && typeof link[REF_KEY] === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernRecord.getLinkedRecordID(): Expected `%s.%s` to be a linked ID, ' + 'was `%s`.', record[ID_KEY], storageKey, JSON.stringify(link)) : invariant(false) : void 0;
173
+ return link[REF_KEY];
154
174
  }
155
175
  /**
156
176
  * @public
@@ -167,9 +187,9 @@ function getLinkedRecordIDs(record, storageKey) {
167
187
  return links;
168
188
  }
169
189
 
170
- !(typeof links === 'object' && Array.isArray(links[require("./RelayStoreUtils").REFS_KEY])) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernRecord.getLinkedRecordIDs(): Expected `%s.%s` to contain an array ' + 'of linked IDs, got `%s`.', record[require("./RelayStoreUtils").ID_KEY], storageKey, JSON.stringify(links)) : require("fbjs/lib/invariant")(false) : void 0; // assume items of the array are ids
190
+ !(typeof links === 'object' && Array.isArray(links[REFS_KEY])) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernRecord.getLinkedRecordIDs(): Expected `%s.%s` to contain an array ' + 'of linked IDs, got `%s`.', record[ID_KEY], storageKey, JSON.stringify(links)) : invariant(false) : void 0; // assume items of the array are ids
171
191
 
172
- return links[require("./RelayStoreUtils").REFS_KEY];
192
+ return links[REFS_KEY];
173
193
  }
174
194
  /**
175
195
  * @public
@@ -186,11 +206,11 @@ function update(prevRecord, nextRecord) {
186
206
 
187
207
  var prevID = getDataID(prevRecord);
188
208
  var nextID = getDataID(nextRecord);
189
- process.env.NODE_ENV !== "production" ? require("fbjs/lib/warning")(prevID === nextID, 'RelayModernRecord: Invalid record update, expected both versions of ' + 'the record to have the same id, got `%s` and `%s`.', prevID, nextID) : void 0; // note: coalesce null/undefined to null
209
+ process.env.NODE_ENV !== "production" ? warning(prevID === nextID, 'RelayModernRecord: Invalid record update, expected both versions of ' + 'the record to have the same id, got `%s` and `%s`.', prevID, nextID) : void 0; // note: coalesce null/undefined to null
190
210
 
191
211
  var prevType = (_getType = getType(prevRecord)) !== null && _getType !== void 0 ? _getType : null;
192
212
  var nextType = (_getType2 = getType(nextRecord)) !== null && _getType2 !== void 0 ? _getType2 : null;
193
- process.env.NODE_ENV !== "production" ? require("fbjs/lib/warning")(prevType === nextType, 'RelayModernRecord: Invalid record update, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, require("./RelayStoreUtils").TYPENAME_KEY, prevType, nextType) : void 0;
213
+ process.env.NODE_ENV !== "production" ? warning(isClientID(nextID) || prevType === nextType, 'RelayModernRecord: Invalid record update, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, TYPENAME_KEY, prevType, nextType) : void 0;
194
214
  }
195
215
 
196
216
  var updated = null;
@@ -199,10 +219,10 @@ function update(prevRecord, nextRecord) {
199
219
  for (var ii = 0; ii < keys.length; ii++) {
200
220
  var key = keys[ii];
201
221
 
202
- if (updated || !require("fbjs/lib/areEqual")(prevRecord[key], nextRecord[key])) {
222
+ if (updated || !areEqual(prevRecord[key], nextRecord[key])) {
203
223
  updated = updated !== null ? updated : (0, _objectSpread2["default"])({}, prevRecord);
204
224
 
205
- if (nextRecord[key] !== require("./RelayStoreUtils").UNPUBLISH_FIELD_SENTINEL) {
225
+ if (nextRecord[key] !== UNPUBLISH_FIELD_SENTINEL) {
206
226
  updated[key] = nextRecord[key];
207
227
  } else {
208
228
  delete updated[key];
@@ -226,11 +246,11 @@ function merge(record1, record2) {
226
246
 
227
247
  var prevID = getDataID(record1);
228
248
  var nextID = getDataID(record2);
229
- process.env.NODE_ENV !== "production" ? require("fbjs/lib/warning")(prevID === nextID, 'RelayModernRecord: Invalid record merge, expected both versions of ' + 'the record to have the same id, got `%s` and `%s`.', prevID, nextID) : void 0; // note: coalesce null/undefined to null
249
+ process.env.NODE_ENV !== "production" ? warning(prevID === nextID, 'RelayModernRecord: Invalid record merge, expected both versions of ' + 'the record to have the same id, got `%s` and `%s`.', prevID, nextID) : void 0; // note: coalesce null/undefined to null
230
250
 
231
251
  var prevType = (_getType3 = getType(record1)) !== null && _getType3 !== void 0 ? _getType3 : null;
232
252
  var nextType = (_getType4 = getType(record2)) !== null && _getType4 !== void 0 ? _getType4 : null;
233
- process.env.NODE_ENV !== "production" ? require("fbjs/lib/warning")(prevType === nextType, 'RelayModernRecord: Invalid record merge, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, require("./RelayStoreUtils").TYPENAME_KEY, prevType, nextType) : void 0;
253
+ process.env.NODE_ENV !== "production" ? warning(isClientID(nextID) || prevType === nextType, 'RelayModernRecord: Invalid record merge, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, TYPENAME_KEY, prevType, nextType) : void 0;
234
254
  }
235
255
 
236
256
  return Object.assign({}, record1, record2);
@@ -244,7 +264,7 @@ function merge(record1, record2) {
244
264
 
245
265
 
246
266
  function freeze(record) {
247
- require("./deepFreeze")(record);
267
+ deepFreeze(record);
248
268
  }
249
269
  /**
250
270
  * @public
@@ -257,15 +277,15 @@ function setValue(record, storageKey, value) {
257
277
  if (process.env.NODE_ENV !== "production") {
258
278
  var prevID = getDataID(record);
259
279
 
260
- if (storageKey === require("./RelayStoreUtils").ID_KEY) {
261
- process.env.NODE_ENV !== "production" ? require("fbjs/lib/warning")(prevID === value, 'RelayModernRecord: Invalid field update, expected both versions of ' + 'the record to have the same id, got `%s` and `%s`.', prevID, value) : void 0;
262
- } else if (storageKey === require("./RelayStoreUtils").TYPENAME_KEY) {
280
+ if (storageKey === ID_KEY) {
281
+ process.env.NODE_ENV !== "production" ? warning(prevID === value, 'RelayModernRecord: Invalid field update, expected both versions of ' + 'the record to have the same id, got `%s` and `%s`.', prevID, value) : void 0;
282
+ } else if (storageKey === TYPENAME_KEY) {
263
283
  var _getType5, _value;
264
284
 
265
285
  // note: coalesce null/undefined to null
266
286
  var prevType = (_getType5 = getType(record)) !== null && _getType5 !== void 0 ? _getType5 : null;
267
287
  var nextType = (_value = value) !== null && _value !== void 0 ? _value : null;
268
- process.env.NODE_ENV !== "production" ? require("fbjs/lib/warning")(prevType === nextType, 'RelayModernRecord: Invalid field update, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, require("./RelayStoreUtils").TYPENAME_KEY, prevType, nextType) : void 0;
288
+ process.env.NODE_ENV !== "production" ? warning(isClientID(getDataID(record)) || prevType === nextType, 'RelayModernRecord: Invalid field update, expected both versions of ' + 'record `%s` to have the same `%s` but got conflicting types `%s` ' + 'and `%s`. The GraphQL server likely violated the globally unique ' + 'id requirement by returning the same id for different objects.', prevID, TYPENAME_KEY, prevType, nextType) : void 0;
269
289
  }
270
290
  }
271
291
 
@@ -281,7 +301,7 @@ function setValue(record, storageKey, value) {
281
301
  function setLinkedRecordID(record, storageKey, linkedID) {
282
302
  // See perf note above for why we aren't using computed property access.
283
303
  var link = {};
284
- link[require("./RelayStoreUtils").REF_KEY] = linkedID;
304
+ link[REF_KEY] = linkedID;
285
305
  record[storageKey] = link;
286
306
  }
287
307
  /**
@@ -294,7 +314,7 @@ function setLinkedRecordID(record, storageKey, linkedID) {
294
314
  function setLinkedRecordIDs(record, storageKey, linkedIDs) {
295
315
  // See perf note above for why we aren't using computed property access.
296
316
  var links = {};
297
- links[require("./RelayStoreUtils").REFS_KEY] = linkedIDs;
317
+ links[REFS_KEY] = linkedIDs;
298
318
  record[storageKey] = links;
299
319
  }
300
320
 
@@ -9,6 +9,20 @@
9
9
  */
10
10
  'use strict';
11
11
 
12
+ var areEqual = require("fbjs/lib/areEqual");
13
+
14
+ var invariant = require("fbjs/lib/invariant");
15
+
16
+ var warning = require("fbjs/lib/warning");
17
+
18
+ var _require = require("./RelayConcreteVariables"),
19
+ getFragmentVariables = _require.getFragmentVariables;
20
+
21
+ var _require2 = require("./RelayStoreUtils"),
22
+ FRAGMENT_OWNER_KEY = _require2.FRAGMENT_OWNER_KEY,
23
+ FRAGMENTS_KEY = _require2.FRAGMENTS_KEY,
24
+ ID_KEY = _require2.ID_KEY;
25
+
12
26
  /**
13
27
  * @public
14
28
  *
@@ -34,43 +48,55 @@
34
48
  * using that selector to `lookup()` the results against the environment:
35
49
  *
36
50
  * ```
37
- * const childSelector = getSelector(queryVariables, Child, parent);
51
+ * const childSelector = getSingularSelector(queryVariables, Child, parent);
38
52
  * const childData = environment.lookup(childSelector).data;
39
53
  * ```
40
54
  */
41
- function getSelector(operationVariables, fragment, item) {
42
- !(typeof item === 'object' && item !== null && !Array.isArray(item)) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernSelector: Expected value for fragment `%s` to be an object, got ' + '`%s`.', fragment.name, JSON.stringify(item)) : require("fbjs/lib/invariant")(false) : void 0;
43
-
44
- var dataID = item[require("./RelayStoreUtils").ID_KEY];
45
-
46
- var fragments = item[require("./RelayStoreUtils").FRAGMENTS_KEY];
47
-
48
- var owner = item[require("./RelayStoreUtils").FRAGMENT_OWNER_KEY];
55
+ function getSingularSelector(operationVariables, fragment, item, explicitOwner) {
56
+ !(typeof item === 'object' && item !== null && !Array.isArray(item)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected value for fragment `%s` to be an object, got ' + '`%s`.', fragment.name, JSON.stringify(item)) : invariant(false) : void 0;
57
+ var dataID = item[ID_KEY];
58
+ var fragments = item[FRAGMENTS_KEY];
49
59
 
50
60
  if (typeof dataID === 'string' && typeof fragments === 'object' && fragments !== null && typeof fragments[fragment.name] === 'object' && fragments[fragment.name] !== null) {
51
- var argumentVariables = fragments[fragment.name];
61
+ var _ref, _explicitOwner;
52
62
 
53
- if (owner != null && typeof owner === 'object') {
54
- // $FlowFixMe - TODO T39154660
55
- var typedOwner = owner;
56
- var ownerOperationVariables = typedOwner.variables;
63
+ var argumentVariables = fragments[fragment.name]; // We only use the owner to compute the selector variables if an owner
64
+ // was explicitly passed by the caller, for backwards compatibility.
65
+ // See TODO(T39494051) for details
66
+
67
+ if (explicitOwner != null && typeof explicitOwner === 'object') {
68
+ var ownerOperationVariables = explicitOwner.variables;
57
69
 
58
- var _fragmentVariables = require("./RelayConcreteVariables").getFragmentVariables(fragment, ownerOperationVariables, argumentVariables);
70
+ var _fragmentVariables = getFragmentVariables(fragment, ownerOperationVariables,
71
+ /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
72
+ * suppresses an error found when Flow v0.98 was deployed. To see the
73
+ * error delete this comment and run Flow. */
74
+ argumentVariables);
59
75
 
60
76
  return {
61
- owner: typedOwner,
77
+ owner: explicitOwner,
62
78
  selector: {
63
79
  dataID: dataID,
64
80
  node: fragment,
65
81
  variables: _fragmentVariables
66
82
  }
67
83
  };
68
- }
69
-
70
- var fragmentVariables = require("./RelayConcreteVariables").getFragmentVariables(fragment, operationVariables, argumentVariables);
71
-
84
+ } // For convenience, we read and pass through the owner if one
85
+ // is present in the fragment reference (`item`), but we only
86
+ // use the owner to compute the selector variables if an owner was
87
+ // explicitly passed by the caller, for backwards compatibility.
88
+ // See TODO(T39494051) for details
89
+
90
+
91
+ var owner = (_ref = (_explicitOwner = explicitOwner) !== null && _explicitOwner !== void 0 ? _explicitOwner : item[FRAGMENT_OWNER_KEY]) !== null && _ref !== void 0 ? _ref : null;
92
+ var fragmentVariables = getFragmentVariables(fragment, operationVariables,
93
+ /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
94
+ * suppresses an error found when Flow v0.98 was deployed. To see the
95
+ * error delete this comment and run Flow. */
96
+ argumentVariables);
72
97
  return {
73
- owner: null,
98
+ // $FlowFixMe - TODO T39154660
99
+ owner: owner,
74
100
  selector: {
75
101
  dataID: dataID,
76
102
  node: fragment,
@@ -79,7 +105,16 @@ function getSelector(operationVariables, fragment, item) {
79
105
  };
80
106
  }
81
107
 
82
- process.env.NODE_ENV !== "production" ? require("fbjs/lib/warning")(false, 'RelayModernSelector: Expected object to contain data for fragment `%s`, got ' + '`%s`. Make sure that the parent operation/fragment included fragment ' + '`...%s` without `@relay(mask: false)`.', fragment.name, JSON.stringify(item), fragment.name) : void 0;
108
+ if (process.env.NODE_ENV !== "production") {
109
+ var stringifiedItem = JSON.stringify(item);
110
+
111
+ if (stringifiedItem.length > 499) {
112
+ stringifiedItem = stringifiedItem.substr(0, 498) + "\u2026";
113
+ }
114
+
115
+ process.env.NODE_ENV !== "production" ? warning(false, 'RelayModernSelector: Expected object to contain data for fragment `%s`, got ' + '`%s`. Make sure that the parent operation/fragment included fragment ' + '`...%s` without `@relay(mask: false)`.', fragment.name, stringifiedItem, fragment.name) : void 0;
116
+ }
117
+
83
118
  return null;
84
119
  }
85
120
  /**
@@ -87,15 +122,23 @@ function getSelector(operationVariables, fragment, item) {
87
122
  *
88
123
  * Given the result `items` from a parent that fetched `fragment`, creates a
89
124
  * selector that can be used to read the results of that fragment on those
90
- * items. This is similar to `getSelector` but for "plural" fragments that
125
+ * items. This is similar to `getSingularSelector` but for "plural" fragments that
91
126
  * expect an array of results and therefore return an array of selectors.
92
127
  */
93
128
 
94
129
 
95
- function getSelectorList(operationVariables, fragment, items) {
130
+ function getPluralSelector(operationVariables, fragment, items, owners) {
96
131
  var selectors = null;
97
- items.forEach(function (item) {
98
- var selector = item != null ? getSelector(operationVariables, fragment, item) : null;
132
+
133
+ if (process.env.NODE_ENV !== "production") {
134
+ if (owners != null) {
135
+ process.env.NODE_ENV !== "production" ? warning(items.length === owners.length, 'RelayModernSelector: Expected number of plural values for fragment ' + '`%s` to match number of owners. Received %s values and %s owners.', fragment.name, items.length, owners.length) : void 0;
136
+ }
137
+ }
138
+
139
+ items.forEach(function (item, ii) {
140
+ var owner = owners != null ? owners[ii] : null;
141
+ var selector = item != null ? getSingularSelector(operationVariables, fragment, item, owner) : null;
99
142
 
100
143
  if (selector != null) {
101
144
  selectors = selectors || [];
@@ -104,6 +147,42 @@ function getSelectorList(operationVariables, fragment, items) {
104
147
  });
105
148
  return selectors;
106
149
  }
150
+
151
+ function getSelector(operationVariables, fragment, item, explicitOwner) {
152
+ var selectorOrSelectors;
153
+
154
+ if (item == null) {
155
+ selectorOrSelectors = item;
156
+ } else if (fragment.metadata && fragment.metadata.plural === true) {
157
+ !Array.isArray(item) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected value for fragment `%s` to be an array, got `%s`. ' + 'Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.', fragment.name, JSON.stringify(item), fragment.name) : invariant(false) : void 0;
158
+
159
+ if (explicitOwner !== undefined) {
160
+ !Array.isArray(explicitOwner) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected explcitly provided owner for ' + 'fragment `%s` to be an array, got `%s`.', fragment.name, JSON.stringify(explicitOwner)) : invariant(false) : void 0;
161
+ selectorOrSelectors = getPluralSelector(operationVariables, fragment,
162
+ /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
163
+ * suppresses an error found when Flow v0.98 was deployed. To see the
164
+ * error delete this comment and run Flow. */
165
+ item, explicitOwner);
166
+ } else {
167
+ selectorOrSelectors = getPluralSelector(operationVariables, fragment,
168
+ /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
169
+ * suppresses an error found when Flow v0.98 was deployed. To see the
170
+ * error delete this comment and run Flow. */
171
+ item);
172
+ }
173
+ } else {
174
+ !!Array.isArray(item) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected value for fragment `%s` to be an object, got `%s`. ' + 'Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.', fragment.name, JSON.stringify(item), fragment.name) : invariant(false) : void 0;
175
+
176
+ if (explicitOwner != null) {
177
+ !!Array.isArray(explicitOwner) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected explcitly provided owner for ' + 'fragment `%s` not to be an array, got `%s`.', fragment.name, JSON.stringify(explicitOwner)) : invariant(false) : void 0;
178
+ selectorOrSelectors = getSingularSelector(operationVariables, fragment, item, explicitOwner);
179
+ } else {
180
+ selectorOrSelectors = getSingularSelector(operationVariables, fragment, item);
181
+ }
182
+ }
183
+
184
+ return selectorOrSelectors;
185
+ }
107
186
  /**
108
187
  * @public
109
188
  *
@@ -116,7 +195,7 @@ function getSelectorList(operationVariables, fragment, items) {
116
195
  */
117
196
 
118
197
 
119
- function getSelectorsFromObject(operationVariables, fragments, object) {
198
+ function getSelectorsFromObject(operationVariables, fragments, object, owners) {
120
199
  var selectors = {};
121
200
 
122
201
  for (var _key in fragments) {
@@ -124,13 +203,11 @@ function getSelectorsFromObject(operationVariables, fragments, object) {
124
203
  var fragment = fragments[_key];
125
204
  var item = object[_key];
126
205
 
127
- if (item == null) {
128
- selectors[_key] = item;
129
- } else if (fragment.metadata && fragment.metadata.plural === true) {
130
- !Array.isArray(item) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernSelector: Expected value for key `%s` to be an array, got `%s`. ' + 'Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.', _key, JSON.stringify(item), fragment.name) : require("fbjs/lib/invariant")(false) : void 0;
131
- selectors[_key] = getSelectorList(operationVariables, fragment, item);
206
+ if (owners != null) {
207
+ !owners.hasOwnProperty(_key) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected explcitly provided owner for ' + 'fragment `%s` under key `%s` to exist.', fragment.name, _key) : invariant(false) : void 0;
208
+ var explicitOwner = owners[_key];
209
+ selectors[_key] = getSelector(operationVariables, fragment, item, explicitOwner);
132
210
  } else {
133
- !!Array.isArray(item) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernFragmentSpecResolver: Expected value for key `%s` to be an object, got `%s`. ' + 'Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.', _key, JSON.stringify(item), fragment.name) : require("fbjs/lib/invariant")(false) : void 0;
134
211
  selectors[_key] = getSelector(operationVariables, fragment, item);
135
212
  }
136
213
  }
@@ -156,21 +233,32 @@ function getDataIDsFromObject(fragments, object) {
156
233
  if (fragments.hasOwnProperty(_key2)) {
157
234
  var fragment = fragments[_key2];
158
235
  var item = object[_key2];
159
-
160
- if (item == null) {
161
- ids[_key2] = item;
162
- } else if (fragment.metadata && fragment.metadata.plural === true) {
163
- !Array.isArray(item) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernSelector: Expected value for key `%s` to be an array, got `%s`. ' + 'Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.', _key2, JSON.stringify(item), fragment.name) : require("fbjs/lib/invariant")(false) : void 0;
164
- ids[_key2] = getDataIDs(fragment, item);
165
- } else {
166
- !!Array.isArray(item) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernFragmentSpecResolver: Expected value for key `%s` to be an object, got `%s`. ' + 'Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.', _key2, JSON.stringify(item), fragment.name) : require("fbjs/lib/invariant")(false) : void 0;
167
- ids[_key2] = getDataID(fragment, item);
168
- }
236
+ ids[_key2] = getDataIDsFromFragment(fragment, item);
169
237
  }
170
238
  }
171
239
 
172
240
  return ids;
173
241
  }
242
+
243
+ function getDataIDsFromFragment(fragment, item) {
244
+ var idOrIDs;
245
+
246
+ if (item == null) {
247
+ idOrIDs = item;
248
+ } else if (fragment.metadata && fragment.metadata.plural === true) {
249
+ !Array.isArray(item) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected value for fragment `%s` to be an array, got `%s`. ' + 'Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.', fragment.name, JSON.stringify(item), fragment.name) : invariant(false) : void 0;
250
+ /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
251
+ * suppresses an error found when Flow v0.98 was deployed. To see the error
252
+ * delete this comment and run Flow. */
253
+
254
+ idOrIDs = getDataIDs(fragment, item);
255
+ } else {
256
+ !!Array.isArray(item) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernFragmentSpecResolver: Expected value for fragment `%s` to be an object, got `%s`. ' + 'Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.', fragment.name, JSON.stringify(item), fragment.name) : invariant(false) : void 0;
257
+ idOrIDs = getDataID(fragment, item);
258
+ }
259
+
260
+ return idOrIDs;
261
+ }
174
262
  /**
175
263
  * @internal
176
264
  */
@@ -194,15 +282,14 @@ function getDataIDs(fragment, items) {
194
282
 
195
283
 
196
284
  function getDataID(fragment, item) {
197
- !(typeof item === 'object' && item !== null && !Array.isArray(item)) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernSelector: Expected value for fragment `%s` to be an object, got ' + '`%s`.', fragment.name, JSON.stringify(item)) : require("fbjs/lib/invariant")(false) : void 0;
198
-
199
- var dataID = item[require("./RelayStoreUtils").ID_KEY];
285
+ !(typeof item === 'object' && item !== null && !Array.isArray(item)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected value for fragment `%s` to be an object, got ' + '`%s`.', fragment.name, JSON.stringify(item)) : invariant(false) : void 0;
286
+ var dataID = item[ID_KEY];
200
287
 
201
288
  if (typeof dataID === 'string') {
202
289
  return dataID;
203
290
  }
204
291
 
205
- process.env.NODE_ENV !== "production" ? require("fbjs/lib/warning")(false, 'RelayModernSelector: Expected object to contain data for fragment `%s`, got ' + '`%s`. Make sure that the parent operation/fragment included fragment ' + '`...%s` without `@relay(mask: false)`.', fragment.name, JSON.stringify(item), fragment.name) : void 0;
292
+ process.env.NODE_ENV !== "production" ? warning(false, 'RelayModernSelector: Expected object to contain data for fragment `%s`, got ' + '`%s`. Make sure that the parent operation/fragment included fragment ' + '`...%s` without `@relay(mask: false)`.', fragment.name, JSON.stringify(item), fragment.name) : void 0;
206
293
  return null;
207
294
  }
208
295
  /**
@@ -217,51 +304,65 @@ function getDataID(fragment, item) {
217
304
  */
218
305
 
219
306
 
220
- function getVariablesFromObject(operationVariables, fragments, object) {
307
+ function getVariablesFromObject(operationVariables, fragments, object, owners) {
221
308
  var variables = {};
222
309
 
223
310
  for (var _key3 in fragments) {
224
311
  if (fragments.hasOwnProperty(_key3)) {
225
- var _ret = function () {
226
- var fragment = fragments[_key3];
227
- var item = object[_key3];
228
-
229
- if (item == null) {
230
- return "continue";
231
- } else if (fragment.metadata && fragment.metadata.plural === true) {
232
- !Array.isArray(item) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernSelector: Expected value for key `%s` to be an array, got `%s`. ' + 'Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.', _key3, JSON.stringify(item), fragment.name) : require("fbjs/lib/invariant")(false) : void 0;
233
- item.forEach(function (value) {
234
- if (value != null) {
235
- var itemVariables = getVariables(operationVariables, fragment, value);
236
-
237
- if (itemVariables) {
238
- Object.assign(variables, itemVariables);
239
- }
240
- }
241
- });
242
- } else {
243
- !!Array.isArray(item) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'RelayModernFragmentSpecResolver: Expected value for key `%s` to be an object, got `%s`. ' + 'Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.', _key3, JSON.stringify(item), fragment.name) : require("fbjs/lib/invariant")(false) : void 0;
244
- var itemVariables = getVariables(operationVariables, fragment, item);
245
-
246
- if (itemVariables) {
247
- Object.assign(variables, itemVariables);
248
- }
249
- }
250
- }();
312
+ var fragment = fragments[_key3];
313
+ var item = object[_key3];
314
+
315
+ if (owners != null) {
316
+ !owners.hasOwnProperty(_key3) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected explcitly provided owner for ' + 'fragment `%s` under key `%s` to exist.', fragment.name, _key3) : invariant(false) : void 0;
317
+ var explicitOwner = owners[_key3];
318
+ var itemVariables = getVariablesFromFragment(operationVariables, fragment, item, explicitOwner);
319
+ Object.assign(variables, itemVariables);
320
+ } else {
321
+ var _itemVariables = getVariablesFromFragment(operationVariables, fragment, item);
251
322
 
252
- if (_ret === "continue") continue;
323
+ Object.assign(variables, _itemVariables);
324
+ }
253
325
  }
254
326
  }
255
327
 
256
328
  return variables;
257
329
  }
258
- /**
259
- * @internal
260
- */
261
330
 
331
+ function getVariablesFromFragment(operationVariables, fragment, item, explicitOwner) {
332
+ var _fragment$metadata;
333
+
334
+ if (item == null) {
335
+ return {};
336
+ } else if (((_fragment$metadata = fragment.metadata) === null || _fragment$metadata === void 0 ? void 0 : _fragment$metadata.plural) === true) {
337
+ !Array.isArray(item) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected value for fragment `%s` to be an array, got `%s`. ' + 'Remove `@relay(plural: true)` from fragment `%s` to allow the prop to be an object.', fragment.name, JSON.stringify(item), fragment.name) : invariant(false) : void 0;
338
+
339
+ if (explicitOwner !== undefined) {
340
+ !Array.isArray(explicitOwner) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected explcitly provided owner for ' + 'fragment `%s` to be an array, got `%s`.', fragment.name, JSON.stringify(explicitOwner)) : invariant(false) : void 0;
341
+ return getVariablesFromPluralFragment(operationVariables, fragment,
342
+ /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
343
+ * suppresses an error found when Flow v0.98 was deployed. To see the
344
+ * error delete this comment and run Flow. */
345
+ item, explicitOwner);
346
+ } else {
347
+ /* $FlowFixMe(>=0.98.0 site=www,mobile,react_native_fb,oss) This comment
348
+ * suppresses an error found when Flow v0.98 was deployed. To see the
349
+ * error delete this comment and run Flow. */
350
+ return getVariablesFromPluralFragment(operationVariables, fragment, item);
351
+ }
352
+ } else {
353
+ !!Array.isArray(item) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernFragmentSpecResolver: Expected value for fragment `%s` to be an object, got `%s`. ' + 'Add `@relay(plural: true)` to fragment `%s` to allow the prop to be an array of items.', fragment.name, JSON.stringify(item), fragment.name) : invariant(false) : void 0;
354
+
355
+ if (explicitOwner !== undefined) {
356
+ !!Array.isArray(explicitOwner) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernSelector: Expected explcitly provided owner for ' + 'fragment `%s` not to be an array, got `%s`.', fragment.name, JSON.stringify(explicitOwner)) : invariant(false) : void 0;
357
+ return getVariablesFromSingularFragment(operationVariables, fragment, item, explicitOwner) || {};
358
+ } else {
359
+ return getVariablesFromSingularFragment(operationVariables, fragment, item) || {};
360
+ }
361
+ }
362
+ }
262
363
 
263
- function getVariables(operationVariables, fragment, item) {
264
- var ownedSelector = getSelector(operationVariables, fragment, item);
364
+ function getVariablesFromSingularFragment(operationVariables, fragment, item, owner) {
365
+ var ownedSelector = getSingularSelector(operationVariables, fragment, item, owner);
265
366
 
266
367
  if (!ownedSelector) {
267
368
  return null;
@@ -269,6 +370,21 @@ function getVariables(operationVariables, fragment, item) {
269
370
 
270
371
  return ownedSelector.selector.variables;
271
372
  }
373
+
374
+ function getVariablesFromPluralFragment(operationVariables, fragment, items, owners) {
375
+ var variables = {};
376
+ items.forEach(function (value, ii) {
377
+ if (value != null) {
378
+ var owner = owners != null ? owners[ii] : null;
379
+ var itemVariables = getVariablesFromSingularFragment(operationVariables, fragment, value, owner);
380
+
381
+ if (itemVariables) {
382
+ Object.assign(variables, itemVariables);
383
+ }
384
+ }
385
+ });
386
+ return variables;
387
+ }
272
388
  /**
273
389
  * @public
274
390
  *
@@ -279,14 +395,24 @@ function getVariables(operationVariables, fragment, item) {
279
395
 
280
396
 
281
397
  function areEqualSelectors(thisSelector, thatSelector) {
282
- return thisSelector.selector.dataID === thatSelector.selector.dataID && thisSelector.selector.node === thatSelector.selector.node && require("fbjs/lib/areEqual")(thisSelector.selector.variables, thatSelector.selector.variables);
398
+ var areVariablesEqual = areEqual(thisSelector.selector.variables, thatSelector.selector.variables);
399
+ var areReaderSelectorsEqual = thisSelector.selector.dataID === thatSelector.selector.dataID && thisSelector.selector.node === thatSelector.selector.node && areVariablesEqual; // NOTE: With fragment ownership we need to also compare if
400
+ // the owners attached to the selectors are the same, otherwise we might
401
+ // skip setting a new selector that has a new owner.
402
+
403
+ return areReaderSelectorsEqual && thisSelector.owner === thatSelector.owner;
283
404
  }
284
405
 
285
406
  module.exports = {
286
407
  areEqualSelectors: areEqualSelectors,
408
+ getDataIDsFromFragment: getDataIDsFromFragment,
287
409
  getDataIDsFromObject: getDataIDsFromObject,
410
+ getSingularSelector: getSingularSelector,
411
+ getPluralSelector: getPluralSelector,
288
412
  getSelector: getSelector,
289
- getSelectorList: getSelectorList,
290
413
  getSelectorsFromObject: getSelectorsFromObject,
414
+ getVariablesFromSingularFragment: getVariablesFromSingularFragment,
415
+ getVariablesFromPluralFragment: getVariablesFromPluralFragment,
416
+ getVariablesFromFragment: getVariablesFromFragment,
291
417
  getVariablesFromObject: getVariablesFromObject
292
418
  };