relay-runtime 4.0.0 → 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 (60) hide show
  1. package/index.js +1 -1
  2. package/lib/ClientID.js +1 -1
  3. package/lib/ConvertToExecuteFunction.js +1 -1
  4. package/lib/DataChecker.js +10 -9
  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 +1 -1
  9. package/lib/RelayConnectionHandler.js +1 -1
  10. package/lib/RelayConnectionInterface.js +1 -1
  11. package/lib/RelayDefaultHandleKey.js +1 -1
  12. package/lib/RelayDefaultHandlerProvider.js +1 -6
  13. package/lib/RelayDefaultMissingFieldHandlers.js +26 -0
  14. package/lib/RelayFeatureFlags.js +3 -5
  15. package/lib/RelayModernEnvironment.js +30 -20
  16. package/lib/RelayModernFragmentOwner.js +1 -1
  17. package/lib/RelayModernFragmentSpecResolver.js +36 -49
  18. package/lib/RelayModernOperationDescriptor.js +1 -1
  19. package/lib/RelayModernQueryExecutor.js +200 -92
  20. package/lib/RelayModernSelector.js +36 -16
  21. package/lib/RelayModernStore.js +14 -8
  22. package/lib/RelayNetwork.js +1 -1
  23. package/lib/RelayNetworkLogger.js +1 -1
  24. package/lib/RelayNetworkTypes.js +1 -1
  25. package/lib/RelayObservable.js +69 -40
  26. package/lib/RelayOperationTracker.js +26 -39
  27. package/lib/RelayPublishQueue.js +24 -19
  28. package/lib/RelayQueryResponseCache.js +1 -1
  29. package/lib/RelayReader.js +23 -5
  30. package/lib/RelayRecordProxy.js +7 -3
  31. package/lib/RelayRecordSourceMutator.js +1 -1
  32. package/lib/RelayRecordSourceProxy.js +5 -2
  33. package/lib/RelayRecordSourceSelectorProxy.js +1 -1
  34. package/lib/RelayRecordState.js +1 -1
  35. package/lib/RelayReferenceMarker.js +4 -3
  36. package/lib/RelayReplaySubject.js +1 -1
  37. package/lib/RelayResponseNormalizer.js +57 -19
  38. package/lib/RelayRuntimeTypes.js +1 -1
  39. package/lib/RelayStoreUtils.js +39 -9
  40. package/lib/RelayViewerHandler.js +2 -49
  41. package/lib/StoreInspector.js +1 -1
  42. package/lib/cloneRelayHandleSourceField.js +1 -1
  43. package/lib/commitLocalUpdate.js +1 -1
  44. package/lib/createRelayContext.js +1 -1
  45. package/lib/deepFreeze.js +1 -1
  46. package/lib/defaultGetDataID.js +24 -0
  47. package/lib/fetchQueryInternal.js +1 -1
  48. package/lib/fetchRelayModernQuery.js +1 -1
  49. package/lib/getFragmentIdentifier.js +1 -1
  50. package/lib/getFragmentSpecIdentifier.js +1 -1
  51. package/lib/getRequestParametersIdentifier.js +1 -1
  52. package/lib/hasOverlappingIDs.js +1 -1
  53. package/lib/index.js +5 -0
  54. package/lib/isPromise.js +1 -1
  55. package/lib/isScalarAndEqual.js +1 -1
  56. package/lib/normalizeRelayPayload.js +2 -5
  57. package/lib/recycleNodesInto.js +7 -1
  58. package/package.json +2 -2
  59. package/relay-runtime.js +2 -2
  60. package/relay-runtime.min.js +2 -2
@@ -4,7 +4,7 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
- * strict-local
7
+ *
8
8
  * @format
9
9
  * @emails oncall+relay
10
10
  */
@@ -16,8 +16,6 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
16
16
 
17
17
  var RelayError = require("./RelayError");
18
18
 
19
- var RelayFeatureFlags = require("./RelayFeatureFlags");
20
-
21
19
  var RelayInMemoryRecordSource = require("./RelayInMemoryRecordSource");
22
20
 
23
21
  var RelayModernRecord = require("./RelayModernRecord");
@@ -28,6 +26,11 @@ var RelayResponseNormalizer = require("./RelayResponseNormalizer");
28
26
 
29
27
  var invariant = require("fbjs/lib/invariant");
30
28
 
29
+ var stableCopy = require("./stableCopy"); // flowlint-next-line untyped-import:off
30
+
31
+
32
+ var warning = require("fbjs/lib/warning");
33
+
31
34
  var _require = require("./ClientID"),
32
35
  generateClientID = _require.generateClientID;
33
36
 
@@ -62,8 +65,9 @@ function () {
62
65
  sink = _ref.sink,
63
66
  source = _ref.source,
64
67
  updater = _ref.updater,
65
- operationTracker = _ref.operationTracker;
66
- this._incrementalPlaceholders = new Map();
68
+ operationTracker = _ref.operationTracker,
69
+ getDataID = _ref.getDataID;
70
+ this._incrementalResults = new Map();
67
71
  this._nextSubscriptionId = 0;
68
72
  this._operation = operation;
69
73
  this._operationLoader = operationLoader;
@@ -76,13 +80,14 @@ function () {
76
80
  this._updater = updater;
77
81
  this._subscriptions = new Map();
78
82
  this._operationTracker = operationTracker;
83
+ this._getDataID = getDataID;
79
84
  var id = this._nextSubscriptionId++;
80
85
  source.subscribe({
81
86
  complete: function complete() {
82
87
  return _this._complete(id);
83
88
  },
84
89
  error: function error(_error2) {
85
- return _this._error(id, _error2);
90
+ return _this._error(_error2);
86
91
  },
87
92
  next: function next(response) {
88
93
  try {
@@ -133,7 +138,7 @@ function () {
133
138
  this._publishQueue.run();
134
139
  }
135
140
 
136
- this._incrementalPlaceholders.clear();
141
+ this._incrementalResults.clear();
137
142
 
138
143
  this._completeOperationTracker();
139
144
  };
@@ -163,7 +168,7 @@ function () {
163
168
  return _this2._complete(_id2);
164
169
  },
165
170
  error: function error(_error3) {
166
- return _this2._error(_id2, _error3);
171
+ return _this2._error(_error3);
167
172
  },
168
173
  start: function start(subscription) {
169
174
  return _this2._start(_id2, subscription);
@@ -184,7 +189,7 @@ function () {
184
189
  }
185
190
  };
186
191
 
187
- _proto._error = function _error(_id, error) {
192
+ _proto._error = function _error(error) {
188
193
  this.cancel();
189
194
 
190
195
  this._sink.error(error);
@@ -192,8 +197,8 @@ function () {
192
197
 
193
198
  _proto._start = function _start(id, subscription) {
194
199
  this._subscriptions.set(id, subscription);
195
- }; // Handle a raw GraphQL response.
196
-
200
+ } // Handle a raw GraphQL response.
201
+ ;
197
202
 
198
203
  _proto._next = function _next(_id, response) {
199
204
  var _this3 = this;
@@ -245,10 +250,14 @@ function () {
245
250
  label = response.label;
246
251
 
247
252
  if (path != null || label != null) {
248
- if (typeof label !== 'string' || !Array.isArray(path)) {
249
- !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernQueryExecutor: invalid incremental payload, expected ' + '`path` and `label` to either both be null/undefined, or ' + '`path` to be an `Array<string | number>` and `label` to be a ' + '`string`.') : invariant(false) : void 0;
253
+ if (typeof label === 'string' && Array.isArray(path)) {
254
+ this._processIncrementalResponse({
255
+ path: path,
256
+ label: label,
257
+ response: responseWithData
258
+ });
250
259
  } else {
251
- this._processIncrementalResponse(label, path, responseWithData);
260
+ !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernQueryExecutor: invalid incremental payload, expected ' + '`path` and `label` to either both be null/undefined, or ' + '`path` to be an `Array<string | number>` and `label` to be a ' + '`string`.') : invariant(false) : void 0;
252
261
  }
253
262
  } else {
254
263
  this._processResponse(responseWithData);
@@ -262,7 +271,7 @@ function () {
262
271
  !(this._optimisticUpdate === null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'environment.execute: only support one optimistic response per ' + 'execute.') : invariant(false) : void 0;
263
272
  var payload = normalizeResponse(response, this._operation.root, ROOT_TYPE, []
264
273
  /* path */
265
- );
274
+ , this._getDataID);
266
275
  var incrementalPlaceholders = payload.incrementalPlaceholders,
267
276
  moduleImportPayloads = payload.moduleImportPayloads;
268
277
 
@@ -283,6 +292,8 @@ function () {
283
292
  };
284
293
 
285
294
  _proto._processResponse = function _processResponse(response) {
295
+ var _response$extensions2;
296
+
286
297
  if (this._optimisticUpdate !== null) {
287
298
  this._publishQueue.revertUpdate(this._optimisticUpdate);
288
299
 
@@ -291,9 +302,9 @@ function () {
291
302
 
292
303
  var payload = normalizeResponse(response, this._operation.root, ROOT_TYPE, []
293
304
  /* path */
294
- );
305
+ , this._getDataID);
295
306
 
296
- this._incrementalPlaceholders.clear();
307
+ this._incrementalResults.clear();
297
308
 
298
309
  this._source.clear();
299
310
 
@@ -304,12 +315,20 @@ function () {
304
315
  var updatedOwners = this._publishQueue.run();
305
316
 
306
317
  this._updateOperationTracker(updatedOwners);
307
- };
318
+
319
+ if (payload.incrementalPlaceholders && payload.incrementalPlaceholders.length !== 0 && ((_response$extensions2 = response.extensions) === null || _response$extensions2 === void 0 ? void 0 : _response$extensions2.is_final) === true) {
320
+ // The query has defer/stream selections that are enabled, but the server
321
+ // indicated that this is a "final" payload: no incremental payloads will
322
+ // be delivered. Warn that the query was (likely) executed on the server
323
+ // in non-streaming mode, with incremental delivery disabled.
324
+ process.env.NODE_ENV !== "production" ? warning(false, 'RelayModernEnvironment: Operation `%s` contains @defer/@stream ' + 'directives but was executed in non-streaming mode. See ' + 'https://fburl.com/relay-incremental-delivery-non-streaming-warning.', this._operation.node.params.name) : void 0;
325
+ }
326
+ }
308
327
  /**
309
328
  * Handles any follow-up actions for a Relay payload for @match, @defer,
310
329
  * and (in the future) @stream directives.
311
330
  */
312
-
331
+ ;
313
332
 
314
333
  _proto._processPayloadFollowups = function _processPayloadFollowups(payload) {
315
334
  var _this4 = this;
@@ -326,12 +345,11 @@ function () {
326
345
  }
327
346
 
328
347
  if (incrementalPlaceholders && incrementalPlaceholders.length !== 0) {
329
- !RelayFeatureFlags.ENABLE_INCREMENTAL_DELIVERY ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Unexpected use of @defer/@stream in ' + 'operation `%s`.', this._operation.node.params.name) : invariant(false) : void 0;
330
348
  incrementalPlaceholders.forEach(function (incrementalPlaceholder) {
331
349
  _this4._processIncrementalPlaceholder(payload, incrementalPlaceholder);
332
350
  });
333
351
  }
334
- };
352
+ }
335
353
  /**
336
354
  * Processes a ModuleImportPayload, asynchronously resolving the normalization
337
355
  * AST and using it to normalize the field data into a RelayResponsePayload.
@@ -339,34 +357,47 @@ function () {
339
357
  * defer, stream, etc); these are handled by calling
340
358
  * `_processPayloadFollowups()`.
341
359
  */
342
-
360
+ ;
343
361
 
344
362
  _proto._processModuleImportPayload = function _processModuleImportPayload(moduleImportPayload, operationLoader) {
345
363
  var _this5 = this;
346
364
 
347
- var id = this._nextSubscriptionId++; // Observable.from(operationLoader.load()) wouldn't catch synchronous errors
348
- // thrown by the load function, which is user-defined. Guard against that
349
- // with Observable.from(new Promise(<work>)).
365
+ var syncOperation = operationLoader.get(moduleImportPayload.operationReference);
350
366
 
351
- RelayObservable.from(new Promise(function (resolve, reject) {
352
- operationLoader.load(moduleImportPayload.operationReference).then(resolve, reject);
353
- })).map(function (operation) {
354
- if (operation != null) {
355
- _this5._schedule(function () {
356
- _this5._handleModuleImportPayload(moduleImportPayload, operation);
357
- });
358
- }
359
- }).subscribe({
360
- complete: function complete() {
361
- return _this5._complete(id);
362
- },
363
- error: function error(_error4) {
364
- return _this5._error(id, _error4);
365
- },
366
- start: function start(subscription) {
367
- return _this5._start(id, subscription);
368
- }
369
- });
367
+ if (syncOperation != null) {
368
+ // If the operation module is available synchronously, normalize the
369
+ // data synchronously.
370
+ this._schedule(function () {
371
+ _this5._handleModuleImportPayload(moduleImportPayload, syncOperation);
372
+ });
373
+ } else {
374
+ // Otherwise load the operation module and schedule a task to normalize
375
+ // the data when the module is available.
376
+ var _id3 = this._nextSubscriptionId++; // Observable.from(operationLoader.load()) wouldn't catch synchronous
377
+ // errors thrown by the load function, which is user-defined. Guard
378
+ // against that with Observable.from(new Promise(<work>)).
379
+
380
+
381
+ RelayObservable.from(new Promise(function (resolve, reject) {
382
+ operationLoader.load(moduleImportPayload.operationReference).then(resolve, reject);
383
+ })).map(function (operation) {
384
+ if (operation != null) {
385
+ _this5._schedule(function () {
386
+ _this5._handleModuleImportPayload(moduleImportPayload, operation);
387
+ });
388
+ }
389
+ }).subscribe({
390
+ complete: function complete() {
391
+ return _this5._complete(_id3);
392
+ },
393
+ error: function error(_error4) {
394
+ return _this5._error(_error4);
395
+ },
396
+ start: function start(subscription) {
397
+ return _this5._start(_id3, subscription);
398
+ }
399
+ });
400
+ }
370
401
  };
371
402
 
372
403
  _proto._handleModuleImportPayload = function _handleModuleImportPayload(moduleImportPayload, operation) {
@@ -377,7 +408,7 @@ function () {
377
408
  };
378
409
  var relayPayload = normalizeResponse({
379
410
  data: moduleImportPayload.data
380
- }, selector, moduleImportPayload.typeName, moduleImportPayload.path);
411
+ }, selector, moduleImportPayload.typeName, moduleImportPayload.path, this._getDataID);
381
412
 
382
413
  this._processPayloadFollowups(relayPayload);
383
414
 
@@ -386,39 +417,44 @@ function () {
386
417
  var updatedOwners = this._publishQueue.run();
387
418
 
388
419
  this._updateOperationTracker(updatedOwners);
389
- };
420
+ }
390
421
  /**
391
- * Stores a mapping of label => path => placeholder; at this point the
392
- * executor knows *how* to process the incremental data and has to save
393
- * this until the data is available. The placeholder contains the
394
- * normalization selector, path (for nested defer/stream), and other metadata
395
- * used to normalize the incremental response.
422
+ * The executor now knows that GraphQL responses are expected for a given
423
+ * label/path:
424
+ * - Store the placeholder in order to process any future responses that may
425
+ * arrive.
426
+ * - Then process any responses that had already arrived.
427
+ *
428
+ * The placeholder contains the normalization selector, path (for nested
429
+ * defer/stream), and other metadata used to normalize the incremental
430
+ * response(s).
396
431
  */
397
-
432
+ ;
398
433
 
399
434
  _proto._processIncrementalPlaceholder = function _processIncrementalPlaceholder(relayPayload, placeholder) {
435
+ var _this6 = this;
436
+
400
437
  var _relayPayload$fieldPa;
401
438
 
402
439
  // Update the label => path => placeholder map
403
- var kind = placeholder.kind,
404
- label = placeholder.label,
440
+ var label = placeholder.label,
405
441
  path = placeholder.path;
406
442
  var pathKey = path.map(String).join('.');
407
443
 
408
- var dataForLabel = this._incrementalPlaceholders.get(label);
444
+ var resultForLabel = this._incrementalResults.get(label);
409
445
 
410
- if (dataForLabel == null) {
411
- dataForLabel = {
412
- kind: kind,
413
- placeholdersByPath: new Map()
414
- };
446
+ if (resultForLabel == null) {
447
+ resultForLabel = new Map();
415
448
 
416
- this._incrementalPlaceholders.set(label, dataForLabel);
417
- } else if (dataForLabel.kind !== kind) {
418
- !false ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Received inconsistent data for label `%s`, ' + 'expected `@%s` data but got `@%s` data.', label, dataForLabel.kind, kind) : invariant(false) : void 0;
449
+ this._incrementalResults.set(label, resultForLabel);
419
450
  }
420
451
 
421
- dataForLabel.placeholdersByPath.set(pathKey, placeholder); // Store references to the parent node to allow detecting concurrent
452
+ var resultForPath = resultForLabel.get(pathKey);
453
+ var pendingResponses = resultForPath != null && resultForPath.kind === 'response' ? resultForPath.responses : null;
454
+ resultForLabel.set(pathKey, {
455
+ kind: 'placeholder',
456
+ placeholder: placeholder
457
+ }); // Store references to the parent node to allow detecting concurrent
422
458
  // modifications to the parent before items arrive and to replay
423
459
  // handle field payloads to account for new information on source records.
424
460
 
@@ -438,34 +474,86 @@ function () {
438
474
  // ancestor.field links to the parent record (example: connections)
439
475
  fieldID === parentID
440
476
  );
441
- }); // null-check is for flow; if an incremental payload exists for some id that
442
- // record should also exist.
477
+ }); // If an incremental payload exists for some id that record should also
478
+ // exist.
479
+
480
+ !(parentRecord != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected record `%s` to exist.', parentID) : invariant(false) : void 0;
481
+ var nextParentRecord;
482
+ var nextParentPayloads;
483
+
484
+ var previousParentEntry = this._source.get(parentID);
485
+
486
+ if (previousParentEntry != null) {
487
+ // If a previous entry exists, merge the previous/next records and
488
+ // payloads together.
489
+ nextParentRecord = RelayModernRecord.update(previousParentEntry.record, parentRecord);
490
+ var handlePayloads = new Map();
491
+
492
+ var dedupePayload = function dedupePayload(payload) {
493
+ var key = stableStringify(payload);
494
+ handlePayloads.set(key, payload);
495
+ };
496
+
497
+ previousParentEntry.fieldPayloads.forEach(dedupePayload);
498
+ parentPayloads.forEach(dedupePayload);
499
+ nextParentPayloads = Array.from(handlePayloads.values());
500
+ } else {
501
+ nextParentRecord = parentRecord;
502
+ nextParentPayloads = parentPayloads;
503
+ }
443
504
 
444
- if (parentRecord != null) {
445
- this._source.set(parentID, {
446
- record: parentRecord,
447
- fieldPayloads: parentPayloads
505
+ this._source.set(parentID, {
506
+ record: nextParentRecord,
507
+ fieldPayloads: nextParentPayloads
508
+ }); // If there were any queued responses, process them now that placeholders
509
+ // are in place
510
+
511
+
512
+ if (pendingResponses != null) {
513
+ pendingResponses.forEach(function (incrementalResponse) {
514
+ _this6._schedule(function () {
515
+ _this6._processIncrementalResponse(incrementalResponse);
516
+ });
448
517
  });
449
518
  }
450
- };
519
+ }
451
520
  /**
452
521
  * Lookup the placeholder the describes how to process an incremental
453
522
  * response, normalize/publish it, and process any nested defer/match/stream
454
523
  * metadata.
455
524
  */
525
+ ;
456
526
 
527
+ _proto._processIncrementalResponse = function _processIncrementalResponse(incrementalResponse) {
528
+ var label = incrementalResponse.label,
529
+ path = incrementalResponse.path,
530
+ response = incrementalResponse.response;
457
531
 
458
- _proto._processIncrementalResponse = function _processIncrementalResponse(label, path, response) {
459
- !RelayFeatureFlags.ENABLE_INCREMENTAL_DELIVERY ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Unexpected use of @defer/@stream in ' + 'operation `%s`.', this._operation.node.params.name) : invariant(false) : void 0;
532
+ var resultForLabel = this._incrementalResults.get(label);
460
533
 
461
- var dataForLabel = this._incrementalPlaceholders.get(label);
534
+ if (resultForLabel == null) {
535
+ resultForLabel = new Map();
462
536
 
463
- !(dataForLabel != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Received response for unknown label ' + "'".concat(label, "'. Known labels: ").concat(Array.from(this._incrementalPlaceholders.keys()).join(', '), ".")) : invariant(false) : void 0;
537
+ this._incrementalResults.set(label, resultForLabel);
538
+ }
464
539
 
465
- if (dataForLabel.kind === 'defer') {
540
+ if (label.indexOf('$defer$') !== -1) {
466
541
  var pathKey = path.map(String).join('.');
467
- var placeholder = dataForLabel.placeholdersByPath.get(pathKey);
468
- !(placeholder != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Received response for unknown path `%s` ' + 'for label `%s`. Known paths: %s.', pathKey, label, Array.from(dataForLabel.placeholdersByPath.keys()).join(', ')) : invariant(false) : void 0;
542
+ var resultForPath = resultForLabel.get(pathKey);
543
+
544
+ if (resultForPath == null) {
545
+ resultForPath = {
546
+ kind: 'response',
547
+ responses: [incrementalResponse]
548
+ };
549
+ resultForLabel.set(pathKey, resultForPath);
550
+ return;
551
+ } else if (resultForPath.kind === 'response') {
552
+ resultForPath.responses.push(incrementalResponse);
553
+ return;
554
+ }
555
+
556
+ var placeholder = resultForPath.placeholder;
469
557
  !(placeholder.kind === 'defer') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected data for path `%s` for label `%s` ' + 'to be data for @defer, was `@%s`.', pathKey, label, placeholder.kind) : invariant(false) : void 0;
470
558
 
471
559
  this._processDeferResponse(label, path, placeholder, response);
@@ -476,9 +564,22 @@ function () {
476
564
  // (the item index is used later to insert the element in the list)
477
565
  var _pathKey = path.slice(0, -2).map(String).join('.');
478
566
 
479
- var _placeholder = dataForLabel.placeholdersByPath.get(_pathKey);
567
+ var _resultForPath = resultForLabel.get(_pathKey);
568
+
569
+ if (_resultForPath == null) {
570
+ _resultForPath = {
571
+ kind: 'response',
572
+ responses: [incrementalResponse]
573
+ };
574
+ resultForLabel.set(_pathKey, _resultForPath);
575
+ return;
576
+ } else if (_resultForPath.kind === 'response') {
577
+ _resultForPath.responses.push(incrementalResponse);
578
+
579
+ return;
580
+ }
480
581
 
481
- !(_placeholder != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Received response for unknown path `%s` ' + 'for label `%s`. Known paths: %s.', _pathKey, label, Array.from(dataForLabel.placeholdersByPath.keys()).join(', ')) : invariant(false) : void 0;
582
+ var _placeholder = _resultForPath.placeholder;
482
583
  !(_placeholder.kind === 'stream') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected data for path `%s` for label `%s` ' + 'to be data for @stream, was `@%s`.', _pathKey, label, _placeholder.kind) : invariant(false) : void 0;
483
584
 
484
585
  this._processStreamResponse(label, path, _placeholder, response);
@@ -487,7 +588,7 @@ function () {
487
588
 
488
589
  _proto._processDeferResponse = function _processDeferResponse(label, path, placeholder, response) {
489
590
  var parentID = placeholder.selector.dataID;
490
- var relayPayload = normalizeResponse(response, placeholder.selector, placeholder.typeName, placeholder.path);
591
+ var relayPayload = normalizeResponse(response, placeholder.selector, placeholder.typeName, placeholder.path, this._getDataID);
491
592
 
492
593
  this._processPayloadFollowups(relayPayload);
493
594
 
@@ -515,14 +616,14 @@ function () {
515
616
  var updatedOwners = this._publishQueue.run();
516
617
 
517
618
  this._updateOperationTracker(updatedOwners);
518
- };
619
+ }
519
620
  /**
520
621
  * Process the data for one item in a @stream field.
521
622
  */
522
-
623
+ ;
523
624
 
524
625
  _proto._processStreamResponse = function _processStreamResponse(label, path, placeholder, response) {
525
- var _field$alias, _data$id, _field$concreteType;
626
+ var _field$alias, _field$concreteType, _this$_getDataID;
526
627
 
527
628
  var parentID = placeholder.parentID,
528
629
  node = placeholder.node,
@@ -549,10 +650,12 @@ function () {
549
650
 
550
651
  var finalPathEntry = path[path.length - 1];
551
652
  var itemIndex = parseInt(finalPathEntry, 10);
552
- !(itemIndex === finalPathEntry && itemIndex >= 0) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected path for @stream to end in a ' + 'positive integer index, got `%s`', finalPathEntry) : invariant(false) : void 0; // Determine the __id of the new item: this must equal the value that would
653
+ !(itemIndex === finalPathEntry && itemIndex >= 0) ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected path for @stream to end in a ' + 'positive integer index, got `%s`', finalPathEntry) : invariant(false) : void 0;
654
+ var typeName = (_field$concreteType = field.concreteType) !== null && _field$concreteType !== void 0 ? _field$concreteType : data[TYPENAME_KEY];
655
+ !(typeof typeName === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected @stream field `%s` to have a ' + '__typename.', field.name) : invariant(false) : void 0; // Determine the __id of the new item: this must equal the value that would
553
656
  // be assigned had the item not been streamed
554
657
 
555
- var itemID = ((_data$id = data.id) !== null && _data$id !== void 0 ? _data$id : prevIDs && prevIDs[itemIndex]) || // Reuse previously generated client IDs
658
+ var itemID = ((_this$_getDataID = this._getDataID(data, typeName)) !== null && _this$_getDataID !== void 0 ? _this$_getDataID : prevIDs && prevIDs[itemIndex]) || // Reuse previously generated client IDs
556
659
  generateClientID(parentID, storageKey, itemIndex);
557
660
  !(typeof itemID === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected id of elements of field `%s` to ' + 'be strings.', storageKey) : invariant(false) : void 0; // Build a selector to normalize the item data with
558
661
 
@@ -560,9 +663,7 @@ function () {
560
663
  dataID: itemID,
561
664
  node: field,
562
665
  variables: variables
563
- };
564
- var typeName = (_field$concreteType = field.concreteType) !== null && _field$concreteType !== void 0 ? _field$concreteType : data[TYPENAME_KEY];
565
- !(typeof typeName === 'string') ? process.env.NODE_ENV !== "production" ? invariant(false, 'RelayModernEnvironment: Expected @stream field `%s` to have a ' + '__typename.', field.name) : invariant(false) : void 0; // Update the cached version of the parent record to reflect the new item:
666
+ }; // Update the cached version of the parent record to reflect the new item:
566
667
  // this is used when subsequent stream payloads arrive to see if there
567
668
  // have been concurrent modifications to the list
568
669
 
@@ -579,7 +680,7 @@ function () {
579
680
  // modified.
580
681
 
581
682
 
582
- var relayPayload = normalizeResponse(response, selector, typeName, (0, _toConsumableArray2["default"])(placeholder.path).concat([responseKey, String(itemIndex)]));
683
+ var relayPayload = normalizeResponse(response, selector, typeName, [].concat((0, _toConsumableArray2["default"])(placeholder.path), [responseKey, String(itemIndex)]), this._getDataID);
583
684
 
584
685
  this._processPayloadFollowups(relayPayload);
585
686
 
@@ -659,7 +760,7 @@ function () {
659
760
  return Executor;
660
761
  }();
661
762
 
662
- function normalizeResponse(response, selector, typeName, path) {
763
+ function normalizeResponse(response, selector, typeName, path, getDataID) {
663
764
  var data = response.data,
664
765
  errors = response.errors;
665
766
  var source = new RelayInMemoryRecordSource();
@@ -667,7 +768,8 @@ function normalizeResponse(response, selector, typeName, path) {
667
768
  source.set(selector.dataID, record);
668
769
  var normalizeResult = RelayResponseNormalizer.normalize(source, selector, data, {
669
770
  handleStrippedNulls: true,
670
- path: path
771
+ path: path,
772
+ getDataID: getDataID
671
773
  });
672
774
  return {
673
775
  errors: errors,
@@ -678,6 +780,12 @@ function normalizeResponse(response, selector, typeName, path) {
678
780
  };
679
781
  }
680
782
 
783
+ function stableStringify(value) {
784
+ var _JSON$stringify;
785
+
786
+ return (_JSON$stringify = JSON.stringify(stableCopy(value))) !== null && _JSON$stringify !== void 0 ? _JSON$stringify : ''; // null-check for flow
787
+ }
788
+
681
789
  module.exports = {
682
790
  execute: execute
683
791
  };
@@ -9,8 +9,6 @@
9
9
  */
10
10
  'use strict';
11
11
 
12
- var RelayFeatureFlags = require("./RelayFeatureFlags");
13
-
14
12
  var areEqual = require("fbjs/lib/areEqual");
15
13
 
16
14
  var invariant = require("fbjs/lib/invariant");
@@ -69,7 +67,11 @@ function getSingularSelector(operationVariables, fragment, item, explicitOwner)
69
67
  if (explicitOwner != null && typeof explicitOwner === 'object') {
70
68
  var ownerOperationVariables = explicitOwner.variables;
71
69
 
72
- var _fragmentVariables = 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);
73
75
 
74
76
  return {
75
77
  owner: explicitOwner,
@@ -87,7 +89,11 @@ function getSingularSelector(operationVariables, fragment, item, explicitOwner)
87
89
 
88
90
 
89
91
  var owner = (_ref = (_explicitOwner = explicitOwner) !== null && _explicitOwner !== void 0 ? _explicitOwner : item[FRAGMENT_OWNER_KEY]) !== null && _ref !== void 0 ? _ref : null;
90
- var fragmentVariables = getFragmentVariables(fragment, operationVariables, argumentVariables);
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);
91
97
  return {
92
98
  // $FlowFixMe - TODO T39154660
93
99
  owner: owner,
@@ -152,9 +158,17 @@ function getSelector(operationVariables, fragment, item, explicitOwner) {
152
158
 
153
159
  if (explicitOwner !== undefined) {
154
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;
155
- selectorOrSelectors = getPluralSelector(operationVariables, fragment, item, explicitOwner);
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);
156
166
  } else {
157
- selectorOrSelectors = getPluralSelector(operationVariables, fragment, item);
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);
158
172
  }
159
173
  } else {
160
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;
@@ -233,6 +247,10 @@ function getDataIDsFromFragment(fragment, item) {
233
247
  idOrIDs = item;
234
248
  } else if (fragment.metadata && fragment.metadata.plural === true) {
235
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
+
236
254
  idOrIDs = getDataIDs(fragment, item);
237
255
  } else {
238
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;
@@ -320,8 +338,15 @@ function getVariablesFromFragment(operationVariables, fragment, item, explicitOw
320
338
 
321
339
  if (explicitOwner !== undefined) {
322
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;
323
- return getVariablesFromPluralFragment(operationVariables, fragment, item, explicitOwner);
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);
324
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. */
325
350
  return getVariablesFromPluralFragment(operationVariables, fragment, item);
326
351
  }
327
352
  } else {
@@ -371,16 +396,11 @@ function getVariablesFromPluralFragment(operationVariables, fragment, items, own
371
396
 
372
397
  function areEqualSelectors(thisSelector, thatSelector) {
373
398
  var areVariablesEqual = areEqual(thisSelector.selector.variables, thatSelector.selector.variables);
374
- var areReaderSelectorsEqual = thisSelector.selector.dataID === thatSelector.selector.dataID && thisSelector.selector.node === thatSelector.selector.node && areVariablesEqual;
375
-
376
- if (RelayFeatureFlags.PREFER_FRAGMENT_OWNER_OVER_CONTEXT) {
377
- // NOTE: If fragment ownership is enabled, we should also compare if
378
- // the owners attached to the selectors are the same, otherwise we might
379
- // skip setting a new selector that has a new owner.
380
- return areReaderSelectorsEqual && thisSelector.owner === thatSelector.owner;
381
- }
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.
382
402
 
383
- return areReaderSelectorsEqual;
403
+ return areReaderSelectorsEqual && thisSelector.owner === thatSelector.owner;
384
404
  }
385
405
 
386
406
  module.exports = {