relay-runtime 11.0.1 → 11.0.2

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 (71) hide show
  1. package/index.js +1 -1
  2. package/index.js.flow +4 -2
  3. package/lib/handlers/RelayDefaultHandlerProvider.js +1 -1
  4. package/lib/handlers/connection/ConnectionHandler.js +1 -1
  5. package/lib/handlers/connection/MutationHandlers.js +1 -1
  6. package/lib/multi-actor-environment/ActorIdentifier.js +23 -0
  7. package/lib/multi-actor-environment/ActorSpecificEnvironment.js +108 -0
  8. package/lib/multi-actor-environment/MultiActorEnvironment.js +156 -0
  9. package/lib/multi-actor-environment/MultiActorEnvironmentTypes.js +11 -0
  10. package/lib/multi-actor-environment/index.js +17 -0
  11. package/lib/mutations/RelayRecordProxy.js +1 -1
  12. package/lib/mutations/RelayRecordSourceMutator.js +1 -1
  13. package/lib/mutations/RelayRecordSourceProxy.js +1 -1
  14. package/lib/mutations/RelayRecordSourceSelectorProxy.js +1 -1
  15. package/lib/mutations/applyOptimisticMutation.js +1 -1
  16. package/lib/mutations/commitMutation.js +1 -1
  17. package/lib/network/RelayNetwork.js +1 -1
  18. package/lib/network/RelayQueryResponseCache.js +1 -1
  19. package/lib/query/GraphQLTag.js +1 -1
  20. package/lib/query/fetchQuery.js +1 -1
  21. package/lib/query/fetchQueryInternal.js +1 -1
  22. package/lib/store/DataChecker.js +1 -1
  23. package/lib/store/{RelayModernQueryExecutor.js → OperationExecutor.js} +81 -37
  24. package/lib/store/RelayConcreteVariables.js +1 -1
  25. package/lib/store/RelayModernEnvironment.js +99 -144
  26. package/lib/store/RelayModernFragmentSpecResolver.js +1 -1
  27. package/lib/store/RelayModernRecord.js +1 -1
  28. package/lib/store/RelayModernSelector.js +1 -1
  29. package/lib/store/RelayModernStore.js +1 -6
  30. package/lib/store/RelayOperationTracker.js +1 -1
  31. package/lib/store/RelayPublishQueue.js +9 -5
  32. package/lib/store/RelayReader.js +63 -10
  33. package/lib/store/RelayReferenceMarker.js +1 -1
  34. package/lib/store/RelayResponseNormalizer.js +47 -22
  35. package/lib/store/RelayStoreReactFlightUtils.js +1 -1
  36. package/lib/store/RelayStoreUtils.js +1 -1
  37. package/lib/store/ResolverFragments.js +57 -0
  38. package/lib/store/cloneRelayHandleSourceField.js +1 -1
  39. package/lib/store/cloneRelayScalarHandleSourceField.js +1 -1
  40. package/lib/store/createRelayContext.js +1 -1
  41. package/lib/store/readInlineData.js +1 -1
  42. package/lib/subscription/requestSubscription.js +18 -7
  43. package/lib/util/RelayConcreteNode.js +1 -0
  44. package/lib/util/RelayFeatureFlags.js +3 -1
  45. package/lib/util/RelayProfiler.js +17 -187
  46. package/lib/util/RelayReplaySubject.js +1 -1
  47. package/lib/util/getRelayHandleKey.js +1 -1
  48. package/lib/util/getRequestIdentifier.js +1 -1
  49. package/multi-actor-environment/ActorIdentifier.js.flow +27 -0
  50. package/multi-actor-environment/ActorSpecificEnvironment.js.flow +189 -0
  51. package/multi-actor-environment/MultiActorEnvironment.js.flow +233 -0
  52. package/multi-actor-environment/MultiActorEnvironmentTypes.js.flow +196 -0
  53. package/multi-actor-environment/index.js.flow +24 -0
  54. package/network/RelayNetworkTypes.js.flow +5 -4
  55. package/package.json +3 -2
  56. package/relay-runtime.js +2 -2
  57. package/relay-runtime.min.js +2 -2
  58. package/store/{RelayModernQueryExecutor.js.flow → OperationExecutor.js.flow} +82 -35
  59. package/store/RelayModernEnvironment.js.flow +88 -131
  60. package/store/RelayModernStore.js.flow +0 -5
  61. package/store/RelayPublishQueue.js.flow +7 -4
  62. package/store/RelayReader.js.flow +57 -5
  63. package/store/RelayResponseNormalizer.js.flow +67 -26
  64. package/store/RelayStoreTypes.js.flow +15 -8
  65. package/store/ResolverFragments.js.flow +125 -0
  66. package/subscription/requestSubscription.js.flow +15 -7
  67. package/util/ReaderNode.js.flow +14 -1
  68. package/util/RelayConcreteNode.js.flow +1 -0
  69. package/util/RelayFeatureFlags.js.flow +4 -0
  70. package/util/RelayProfiler.js.flow +22 -194
  71. package/util/RelayRuntimeTypes.js.flow +3 -1
@@ -76,7 +76,7 @@ export type ExecuteConfig = {|
76
76
  +operation: OperationDescriptor,
77
77
  +operationExecutions: Map<string, ActiveState>,
78
78
  +operationLoader: ?OperationLoader,
79
- +operationTracker?: ?OperationTracker,
79
+ +operationTracker: OperationTracker,
80
80
  +optimisticConfig: ?OptimisticResponseConfig,
81
81
  +publishQueue: PublishQueue,
82
82
  +reactFlightPayloadDeserializer?: ?ReactFlightPayloadDeserializer,
@@ -133,7 +133,7 @@ class Executor {
133
133
  _operation: OperationDescriptor;
134
134
  _operationExecutions: Map<string, ActiveState>;
135
135
  _operationLoader: ?OperationLoader;
136
- _operationTracker: ?OperationTracker;
136
+ _operationTracker: OperationTracker;
137
137
  _operationUpdateEpochs: Map<string, number>;
138
138
  _optimisticUpdates: null | Array<OptimisticUpdate>;
139
139
  _pendingModulePayloadsCount: number;
@@ -244,6 +244,7 @@ class Executor {
244
244
  optimisticUpdates.forEach(update =>
245
245
  this._publishQueue.revertUpdate(update),
246
246
  );
247
+ // OK: run revert on cancel
247
248
  this._publishQueue.run();
248
249
  }
249
250
  this._incrementalResults.clear();
@@ -276,7 +277,7 @@ class Executor {
276
277
  }
277
278
  default:
278
279
  (this._state: empty);
279
- invariant(false, 'RelayModernQueryExecutor: invalid executor state.');
280
+ invariant(false, 'OperationExecutor: invalid executor state.');
280
281
  }
281
282
  this._operationExecutions.set(
282
283
  this._operation.request.identifier,
@@ -403,7 +404,7 @@ class Executor {
403
404
  if (isOptimistic && this._state !== 'started') {
404
405
  invariant(
405
406
  false,
406
- 'RelayModernQueryExecutor: optimistic payload received after server payload.',
407
+ 'OperationExecutor: optimistic payload received after server payload.',
407
408
  );
408
409
  }
409
410
  if (isOptimistic) {
@@ -449,6 +450,7 @@ class Executor {
449
450
  nonIncrementalResponses,
450
451
  incrementalResponses,
451
452
  ] = partitionGraphQLResponses(responsesWithData);
453
+ const hasNonIncrementalResponses = nonIncrementalResponses.length > 0;
452
454
 
453
455
  // In theory this doesn't preserve the ordering of the batch.
454
456
  // The idea is that a batch is always:
@@ -457,16 +459,20 @@ class Executor {
457
459
  // The non-incremental payload can appear if the server sends a batch
458
460
  // with the initial payload followed by some early-to-resolve incremental
459
461
  // payloads (although, can that even happen?)
460
- if (nonIncrementalResponses.length > 0) {
462
+ if (hasNonIncrementalResponses) {
461
463
  const payloadFollowups = this._processResponses(nonIncrementalResponses);
462
- // Please note that we're passing `this._operation` to the publish
463
- // queue here, which will later passed to the store (via notify)
464
- // to indicate that this is an operation that caused the store to update
465
- const updatedOwners = this._publishQueue.run(this._operation);
466
- this._updateOperationTracker(updatedOwners);
464
+
465
+ if (!RelayFeatureFlags.ENABLE_BATCHED_STORE_UPDATES) {
466
+ const updatedOwners = this._publishQueue.run(this._operation);
467
+ this._updateOperationTracker(updatedOwners);
468
+ }
469
+
467
470
  this._processPayloadFollowups(payloadFollowups);
468
- if (this._incrementalPayloadsPending && !this._retainDisposable) {
469
- this._retainDisposable = this._store.retain(this._operation);
471
+
472
+ if (!RelayFeatureFlags.ENABLE_BATCHED_STORE_UPDATES) {
473
+ if (this._incrementalPayloadsPending && !this._retainDisposable) {
474
+ this._retainDisposable = this._store.retain(this._operation);
475
+ }
470
476
  }
471
477
  }
472
478
 
@@ -474,13 +480,46 @@ class Executor {
474
480
  const payloadFollowups = this._processIncrementalResponses(
475
481
  incrementalResponses,
476
482
  );
477
- // For the incremental case, we're only handling follow-up responses
478
- // for already initiated operation (and we're not passing it to
479
- // the run(...) call)
480
- const updatedOwners = this._publishQueue.run();
481
- this._updateOperationTracker(updatedOwners);
483
+ if (!RelayFeatureFlags.ENABLE_BATCHED_STORE_UPDATES) {
484
+ // For the incremental case, we're only handling follow-up responses
485
+ // for already initiated operation (and we're not passing it to
486
+ // the run(...) call)
487
+ const updatedOwners = this._publishQueue.run();
488
+ this._updateOperationTracker(updatedOwners);
489
+ }
482
490
  this._processPayloadFollowups(payloadFollowups);
483
491
  }
492
+ if (
493
+ this._isSubscriptionOperation &&
494
+ RelayFeatureFlags.ENABLE_UNIQUE_SUBSCRIPTION_ROOT
495
+ ) {
496
+ // We attach the id to allow the `requestSubscription` to read from the store using
497
+ // the current id in its `onNext` callback
498
+ if (responsesWithData[0].extensions == null) {
499
+ // $FlowFixMe[cannot-write]
500
+ responsesWithData[0].extensions = {
501
+ __relay_subscription_root_id: this._operation.fragment.dataID,
502
+ };
503
+ } else {
504
+ responsesWithData[0].extensions.__relay_subscription_root_id = this._operation.fragment.dataID;
505
+ }
506
+ }
507
+
508
+ if (RelayFeatureFlags.ENABLE_BATCHED_STORE_UPDATES) {
509
+ // OK: run once after each new payload
510
+ // If we have non-incremental responses, we passing `this._operation` to
511
+ // the publish queue here, which will later be passed to the store (via
512
+ // notify) to indicate that this operation caused the store to update
513
+ const updatedOwners = this._publishQueue.run(
514
+ hasNonIncrementalResponses ? this._operation : undefined,
515
+ );
516
+ if (hasNonIncrementalResponses) {
517
+ if (this._incrementalPayloadsPending && !this._retainDisposable) {
518
+ this._retainDisposable = this._store.retain(this._operation);
519
+ }
520
+ }
521
+ this._updateOperationTracker(updatedOwners);
522
+ }
484
523
  this._sink.next(response);
485
524
  }
486
525
 
@@ -535,6 +574,8 @@ class Executor {
535
574
  }
536
575
  this._optimisticUpdates = optimisticUpdates;
537
576
  optimisticUpdates.forEach(update => this._publishQueue.applyUpdate(update));
577
+ // OK: only called on construction and when receiving an optimistic payload from network,
578
+ // which doesn't fall-through to the regular next() handling
538
579
  this._publishQueue.run();
539
580
  }
540
581
 
@@ -634,12 +675,13 @@ class Executor {
634
675
  if (this._optimisticUpdates == null) {
635
676
  warning(
636
677
  false,
637
- 'RelayModernQueryExecutor: Unexpected ModuleImport optimistic ' +
678
+ 'OperationExecutor: Unexpected ModuleImport optimistic ' +
638
679
  'update in operation %s.' +
639
680
  this._operation.request.node.params.name,
640
681
  );
641
682
  } else {
642
683
  this._optimisticUpdates.push(...moduleImportOptimisticUpdates);
684
+ // OK: always have to run() after an module import resolves async
643
685
  this._publishQueue.run();
644
686
  }
645
687
  });
@@ -745,8 +787,10 @@ class Executor {
745
787
  }
746
788
  });
747
789
  if (relayPayloads.length > 0) {
748
- const updatedOwners = this._publishQueue.run();
749
- this._updateOperationTracker(updatedOwners);
790
+ if (!RelayFeatureFlags.ENABLE_BATCHED_STORE_UPDATES) {
791
+ const updatedOwners = this._publishQueue.run();
792
+ this._updateOperationTracker(updatedOwners);
793
+ }
750
794
  this._processPayloadFollowups(relayPayloads);
751
795
  }
752
796
  }
@@ -829,6 +873,9 @@ class Executor {
829
873
  moduleImportPayload,
830
874
  getOperation(operation),
831
875
  );
876
+ // OK: always have to run after an async module import resolves
877
+ const updatedOwners = this._publishQueue.run();
878
+ this._updateOperationTracker(updatedOwners);
832
879
  });
833
880
  }
834
881
  })
@@ -855,8 +902,10 @@ class Executor {
855
902
  operation,
856
903
  );
857
904
  this._publishQueue.commitPayload(this._operation, relayPayload);
858
- const updatedOwners = this._publishQueue.run();
859
- this._updateOperationTracker(updatedOwners);
905
+ if (!RelayFeatureFlags.ENABLE_BATCHED_STORE_UPDATES) {
906
+ const updatedOwners = this._publishQueue.run();
907
+ this._updateOperationTracker(updatedOwners);
908
+ }
860
909
  this._processPayloadFollowups([relayPayload]);
861
910
  }
862
911
 
@@ -961,8 +1010,10 @@ class Executor {
961
1010
  const payloadFollowups = this._processIncrementalResponses(
962
1011
  pendingResponses,
963
1012
  );
964
- const updatedOwners = this._publishQueue.run();
965
- this._updateOperationTracker(updatedOwners);
1013
+ if (!RelayFeatureFlags.ENABLE_BATCHED_STORE_UPDATES) {
1014
+ const updatedOwners = this._publishQueue.run();
1015
+ this._updateOperationTracker(updatedOwners);
1016
+ }
966
1017
  this._processPayloadFollowups(payloadFollowups);
967
1018
  }
968
1019
  }
@@ -1291,11 +1342,7 @@ class Executor {
1291
1342
  _updateOperationTracker(
1292
1343
  updatedOwners: ?$ReadOnlyArray<RequestDescriptor>,
1293
1344
  ): void {
1294
- if (
1295
- this._operationTracker != null &&
1296
- updatedOwners != null &&
1297
- updatedOwners.length > 0
1298
- ) {
1345
+ if (updatedOwners != null && updatedOwners.length > 0) {
1299
1346
  this._operationTracker.update(
1300
1347
  this._operation.request,
1301
1348
  new Set(updatedOwners),
@@ -1304,9 +1351,7 @@ class Executor {
1304
1351
  }
1305
1352
 
1306
1353
  _completeOperationTracker() {
1307
- if (this._operationTracker != null) {
1308
- this._operationTracker.complete(this._operation.request);
1309
- }
1354
+ this._operationTracker.complete(this._operation.request);
1310
1355
  }
1311
1356
  }
1312
1357
 
@@ -1324,7 +1369,7 @@ function partitionGraphQLResponses(
1324
1369
  if (label == null || path == null) {
1325
1370
  invariant(
1326
1371
  false,
1327
- 'RelayModernQueryExecutor: invalid incremental payload, expected ' +
1372
+ 'OperationExecutor: invalid incremental payload, expected ' +
1328
1373
  '`path` and `label` to either both be null/undefined, or ' +
1329
1374
  '`path` to be an `Array<string | number>` and `label` to be a ' +
1330
1375
  '`string`.',
@@ -1376,11 +1421,13 @@ function validateOptimisticResponsePayload(
1376
1421
  if (incrementalPlaceholders != null && incrementalPlaceholders.length !== 0) {
1377
1422
  invariant(
1378
1423
  false,
1379
- 'RelayModernQueryExecutor: optimistic responses cannot be returned ' +
1424
+ 'OperationExecutor: optimistic responses cannot be returned ' +
1380
1425
  'for operations that use incremental data delivery (@defer, ' +
1381
1426
  '@stream, and @stream_connection).',
1382
1427
  );
1383
1428
  }
1384
1429
  }
1385
1430
 
1386
- module.exports = {execute};
1431
+ module.exports = {
1432
+ execute,
1433
+ };
@@ -13,9 +13,9 @@
13
13
 
14
14
  'use strict';
15
15
 
16
+ const OperationExecutor = require('./OperationExecutor');
16
17
  const RelayDefaultHandlerProvider = require('../handlers/RelayDefaultHandlerProvider');
17
18
  const RelayFeatureFlags = require('../util/RelayFeatureFlags');
18
- const RelayModernQueryExecutor = require('./RelayModernQueryExecutor');
19
19
  const RelayObservable = require('../network/RelayObservable');
20
20
  const RelayOperationTracker = require('../store/RelayOperationTracker');
21
21
  const RelayPublishQueue = require('./RelayPublishQueue');
@@ -40,14 +40,13 @@ import type {
40
40
  RenderPolicy,
41
41
  Variables,
42
42
  } from '../util/RelayRuntimeTypes';
43
- import type {ActiveState} from './RelayModernQueryExecutor';
44
- import type {TaskScheduler} from './RelayModernQueryExecutor';
43
+ import type {ActiveState, TaskScheduler} from './OperationExecutor';
45
44
  import type {GetDataID} from './RelayResponseNormalizer';
46
45
  import type {
46
+ ExecuteMutationConfig,
47
47
  IEnvironment,
48
48
  LogFunction,
49
49
  MissingFieldHandler,
50
- RequiredFieldLogger,
51
50
  OperationAvailability,
52
51
  OperationDescriptor,
53
52
  OperationLoader,
@@ -57,6 +56,7 @@ import type {
57
56
  PublishQueue,
58
57
  ReactFlightPayloadDeserializer,
59
58
  ReactFlightServerErrorHandler,
59
+ RequiredFieldLogger,
60
60
  SelectorStoreUpdater,
61
61
  SingularReaderSelector,
62
62
  Snapshot,
@@ -108,9 +108,6 @@ class RelayModernEnvironment implements IEnvironment {
108
108
 
109
109
  constructor(config: EnvironmentConfig) {
110
110
  this.configName = config.configName;
111
- const handlerProvider = config.handlerProvider
112
- ? config.handlerProvider
113
- : RelayDefaultHandlerProvider;
114
111
  this._treatMissingFieldsAsNull = config.treatMissingFieldsAsNull === true;
115
112
  const operationLoader = config.operationLoader;
116
113
  const reactFlightPayloadDeserializer =
@@ -150,7 +147,7 @@ class RelayModernEnvironment implements IEnvironment {
150
147
  this._getDataID = config.getDataID ?? defaultGetDataID;
151
148
  this._publishQueue = new RelayPublishQueue(
152
149
  config.store,
153
- handlerProvider,
150
+ config.handlerProvider ?? RelayDefaultHandlerProvider,
154
151
  this._getDataID,
155
152
  );
156
153
  this._scheduler = config.scheduler ?? null;
@@ -240,27 +237,12 @@ class RelayModernEnvironment implements IEnvironment {
240
237
  }
241
238
 
242
239
  applyMutation(optimisticConfig: OptimisticResponseConfig): Disposable {
243
- const subscription = RelayObservable.create(sink => {
244
- const source = RelayObservable.create(_sink => {});
245
- const executor = RelayModernQueryExecutor.execute({
246
- operation: optimisticConfig.operation,
247
- operationExecutions: this._operationExecutions,
248
- operationLoader: this._operationLoader,
249
- optimisticConfig,
250
- publishQueue: this._publishQueue,
251
- reactFlightPayloadDeserializer: this._reactFlightPayloadDeserializer,
252
- reactFlightServerErrorHandler: this._reactFlightServerErrorHandler,
253
- scheduler: this._scheduler,
254
- sink,
255
- source,
256
- store: this._store,
257
- updater: null,
258
- operationTracker: this._operationTracker,
259
- getDataID: this._getDataID,
260
- treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
261
- shouldProcessClientComponents: this._shouldProcessClientComponents,
262
- });
263
- return () => executor.cancel();
240
+ const subscription = this._execute({
241
+ createSource: () => RelayObservable.create(_sink => {}),
242
+ isClientPayload: false,
243
+ operation: optimisticConfig.operation,
244
+ optimisticConfig,
245
+ updater: null,
264
246
  }).subscribe({});
265
247
  return {
266
248
  dispose: () => subscription.unsubscribe(),
@@ -281,29 +263,12 @@ class RelayModernEnvironment implements IEnvironment {
281
263
  }
282
264
 
283
265
  commitPayload(operation: OperationDescriptor, payload: PayloadData): void {
284
- RelayObservable.create(sink => {
285
- const executor = RelayModernQueryExecutor.execute({
286
- operation: operation,
287
- operationExecutions: this._operationExecutions,
288
- operationLoader: this._operationLoader,
289
- optimisticConfig: null,
290
- publishQueue: this._publishQueue,
291
- reactFlightPayloadDeserializer: this._reactFlightPayloadDeserializer,
292
- reactFlightServerErrorHandler: this._reactFlightServerErrorHandler,
293
- scheduler: this._scheduler,
294
- sink,
295
- source: RelayObservable.from({
296
- data: payload,
297
- }),
298
- store: this._store,
299
- updater: null,
300
- operationTracker: this._operationTracker,
301
- getDataID: this._getDataID,
302
- isClientPayload: true,
303
- treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
304
- shouldProcessClientComponents: this._shouldProcessClientComponents,
305
- });
306
- return () => executor.cancel();
266
+ this._execute({
267
+ createSource: () => RelayObservable.from({data: payload}),
268
+ isClientPayload: true,
269
+ operation: operation,
270
+ optimisticConfig: null,
271
+ updater: null,
307
272
  }).subscribe({});
308
273
  }
309
274
 
@@ -372,32 +337,18 @@ class RelayModernEnvironment implements IEnvironment {
372
337
  operation: OperationDescriptor,
373
338
  updater?: ?SelectorStoreUpdater,
374
339
  |}): RelayObservable<GraphQLResponse> {
375
- return RelayObservable.create(sink => {
376
- const source = this._network.execute(
377
- operation.request.node.params,
378
- operation.request.variables,
379
- operation.request.cacheConfig || {},
380
- null,
381
- );
382
- const executor = RelayModernQueryExecutor.execute({
383
- operation,
384
- operationExecutions: this._operationExecutions,
385
- operationLoader: this._operationLoader,
386
- optimisticConfig: null,
387
- publishQueue: this._publishQueue,
388
- reactFlightPayloadDeserializer: this._reactFlightPayloadDeserializer,
389
- reactFlightServerErrorHandler: this._reactFlightServerErrorHandler,
390
- scheduler: this._scheduler,
391
- sink,
392
- source,
393
- store: this._store,
394
- updater,
395
- operationTracker: this._operationTracker,
396
- getDataID: this._getDataID,
397
- treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
398
- shouldProcessClientComponents: this._shouldProcessClientComponents,
399
- });
400
- return () => executor.cancel();
340
+ return this._execute({
341
+ createSource: () =>
342
+ this._network.execute(
343
+ operation.request.node.params,
344
+ operation.request.variables,
345
+ operation.request.cacheConfig || {},
346
+ null,
347
+ ),
348
+ isClientPayload: false,
349
+ operation,
350
+ optimisticConfig: null,
351
+ updater,
401
352
  });
402
353
  }
403
354
 
@@ -417,50 +368,30 @@ class RelayModernEnvironment implements IEnvironment {
417
368
  optimisticUpdater,
418
369
  updater,
419
370
  uploadables,
420
- }: {|
421
- operation: OperationDescriptor,
422
- optimisticUpdater?: ?SelectorStoreUpdater,
423
- optimisticResponse?: ?Object,
424
- updater?: ?SelectorStoreUpdater,
425
- uploadables?: ?UploadableMap,
426
- |}): RelayObservable<GraphQLResponse> {
427
- return RelayObservable.create(sink => {
428
- let optimisticConfig;
429
- if (optimisticResponse || optimisticUpdater) {
430
- optimisticConfig = {
431
- operation: operation,
432
- response: optimisticResponse,
433
- updater: optimisticUpdater,
434
- };
435
- }
436
- const source = this._network.execute(
437
- operation.request.node.params,
438
- operation.request.variables,
439
- {
440
- ...operation.request.cacheConfig,
441
- force: true,
442
- },
443
- uploadables,
444
- );
445
- const executor = RelayModernQueryExecutor.execute({
446
- operation,
447
- operationExecutions: this._operationExecutions,
448
- operationLoader: this._operationLoader,
449
- optimisticConfig,
450
- publishQueue: this._publishQueue,
451
- reactFlightPayloadDeserializer: this._reactFlightPayloadDeserializer,
452
- reactFlightServerErrorHandler: this._reactFlightServerErrorHandler,
453
- scheduler: this._scheduler,
454
- sink,
455
- source,
456
- store: this._store,
457
- updater,
458
- operationTracker: this._operationTracker,
459
- getDataID: this._getDataID,
460
- treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
461
- shouldProcessClientComponents: this._shouldProcessClientComponents,
462
- });
463
- return () => executor.cancel();
371
+ }: ExecuteMutationConfig): RelayObservable<GraphQLResponse> {
372
+ let optimisticConfig;
373
+ if (optimisticResponse || optimisticUpdater) {
374
+ optimisticConfig = {
375
+ operation: operation,
376
+ response: optimisticResponse,
377
+ updater: optimisticUpdater,
378
+ };
379
+ }
380
+ return this._execute({
381
+ createSource: () =>
382
+ this._network.execute(
383
+ operation.request.node.params,
384
+ operation.request.variables,
385
+ {
386
+ ...operation.request.cacheConfig,
387
+ force: true,
388
+ },
389
+ uploadables,
390
+ ),
391
+ isClientPayload: false,
392
+ operation,
393
+ optimisticConfig,
394
+ updater,
464
395
  });
465
396
  }
466
397
 
@@ -479,33 +410,59 @@ class RelayModernEnvironment implements IEnvironment {
479
410
  }: {|
480
411
  operation: OperationDescriptor,
481
412
  source: RelayObservable<GraphQLResponse>,
413
+ |}): RelayObservable<GraphQLResponse> {
414
+ return this._execute({
415
+ createSource: () => source,
416
+ isClientPayload: false,
417
+ operation,
418
+ optimisticConfig: null,
419
+ updater: null,
420
+ });
421
+ }
422
+
423
+ toJSON(): mixed {
424
+ return `RelayModernEnvironment(${this.configName ?? ''})`;
425
+ }
426
+
427
+ _execute({
428
+ createSource,
429
+ isClientPayload,
430
+ operation,
431
+ optimisticConfig,
432
+ updater,
433
+ }: {|
434
+ createSource: () => RelayObservable<GraphQLResponse>,
435
+ isClientPayload: boolean,
436
+ operation: OperationDescriptor,
437
+ optimisticConfig: ?OptimisticResponseConfig,
438
+ updater: ?SelectorStoreUpdater,
482
439
  |}): RelayObservable<GraphQLResponse> {
483
440
  return RelayObservable.create(sink => {
484
- const executor = RelayModernQueryExecutor.execute({
441
+ const executor = OperationExecutor.execute({
442
+ getDataID: this._getDataID,
443
+ isClientPayload,
485
444
  operation,
486
445
  operationExecutions: this._operationExecutions,
487
446
  operationLoader: this._operationLoader,
488
447
  operationTracker: this._operationTracker,
489
- optimisticConfig: null,
448
+ optimisticConfig,
490
449
  publishQueue: this._publishQueue,
491
450
  reactFlightPayloadDeserializer: this._reactFlightPayloadDeserializer,
492
451
  reactFlightServerErrorHandler: this._reactFlightServerErrorHandler,
493
452
  scheduler: this._scheduler,
453
+ shouldProcessClientComponents: this._shouldProcessClientComponents,
494
454
  sink,
495
- source,
455
+ // NOTE: Some product tests expect `Network.execute` to be called only
456
+ // when the Observable is executed.
457
+ source: createSource(),
496
458
  store: this._store,
497
- getDataID: this._getDataID,
498
459
  treatMissingFieldsAsNull: this._treatMissingFieldsAsNull,
499
- shouldProcessClientComponents: this._shouldProcessClientComponents,
460
+ updater,
500
461
  });
501
462
  return () => executor.cancel();
502
463
  });
503
464
  }
504
465
 
505
- toJSON(): mixed {
506
- return `RelayModernEnvironment(${this.configName ?? ''})`;
507
- }
508
-
509
466
  /**
510
467
  * Wraps the network with logging to ensure that network requests are
511
468
  * always logged. Relying on each network callsite to be wrapped is
@@ -16,7 +16,6 @@ const DataChecker = require('./DataChecker');
16
16
  const RelayFeatureFlags = require('../util/RelayFeatureFlags');
17
17
  const RelayModernRecord = require('./RelayModernRecord');
18
18
  const RelayOptimisticRecordSource = require('./RelayOptimisticRecordSource');
19
- const RelayProfiler = require('../util/RelayProfiler');
20
19
  const RelayReader = require('./RelayReader');
21
20
  const RelayReferenceMarker = require('./RelayReferenceMarker');
22
21
  const RelayStoreReactFlightUtils = require('./RelayStoreReactFlightUtils');
@@ -770,8 +769,4 @@ function getAvailabilityStatus(
770
769
  return {status: 'available', fetchTime: operationFetchTime ?? null};
771
770
  }
772
771
 
773
- RelayProfiler.instrumentMethods(RelayModernStore.prototype, {
774
- lookup: 'RelayModernStore.prototype.lookup',
775
- });
776
-
777
772
  module.exports = RelayModernStore;
@@ -12,7 +12,6 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- const ErrorUtils = require('ErrorUtils');
16
15
  const RelayReader = require('./RelayReader');
17
16
  const RelayRecordSource = require('./RelayRecordSource');
18
17
  const RelayRecordSourceMutator = require('../mutations/RelayRecordSourceMutator');
@@ -55,6 +54,10 @@ type PendingUpdater = {|
55
54
  +updater: StoreUpdater,
56
55
  |};
57
56
 
57
+ const applyWithGuard =
58
+ global.ErrorUtils?.applyWithGuard ??
59
+ ((callback, context, args, onError, name) => callback.apply(context, args));
60
+
58
61
  /**
59
62
  * Coordinates the concurrent modification of a `Store` due to optimistic and
60
63
  * non-revertable client updates and server payloads:
@@ -299,7 +302,7 @@ class RelayPublishQueue implements PublishQueue {
299
302
  mutator,
300
303
  this._getDataID,
301
304
  );
302
- ErrorUtils.applyWithGuard(
305
+ applyWithGuard(
303
306
  updater,
304
307
  null,
305
308
  [recordSourceProxy],
@@ -334,7 +337,7 @@ class RelayPublishQueue implements PublishQueue {
334
337
  const processUpdate = optimisticUpdate => {
335
338
  if (optimisticUpdate.storeUpdater) {
336
339
  const {storeUpdater} = optimisticUpdate;
337
- ErrorUtils.applyWithGuard(
340
+ applyWithGuard(
338
341
  storeUpdater,
339
342
  null,
340
343
  [recordSourceProxy],
@@ -355,7 +358,7 @@ class RelayPublishQueue implements PublishQueue {
355
358
  selectorData = lookupSelector(source, operation.fragment);
356
359
  }
357
360
  if (updater) {
358
- ErrorUtils.applyWithGuard(
361
+ applyWithGuard(
359
362
  updater,
360
363
  null,
361
364
  [recordSourceSelectorProxy, selectorData],