react-server-dom-webpack 18.3.0-canary-a870b2d54-20240314 → 18.3.0-canary-4b84f1161-20240318

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 (39) hide show
  1. package/cjs/react-server-dom-webpack-client.browser.development.js +176 -272
  2. package/cjs/react-server-dom-webpack-client.browser.production.js +146 -127
  3. package/cjs/react-server-dom-webpack-client.browser.production.min.js +25 -24
  4. package/cjs/react-server-dom-webpack-client.browser.production.min.js.map +1 -1
  5. package/cjs/react-server-dom-webpack-client.edge.development.js +181 -324
  6. package/cjs/react-server-dom-webpack-client.edge.production.js +151 -168
  7. package/cjs/react-server-dom-webpack-client.edge.production.min.js +30 -30
  8. package/cjs/react-server-dom-webpack-client.edge.production.min.js.map +1 -1
  9. package/cjs/react-server-dom-webpack-client.node.development.js +181 -324
  10. package/cjs/react-server-dom-webpack-client.node.production.js +151 -168
  11. package/cjs/react-server-dom-webpack-client.node.production.min.js +29 -28
  12. package/cjs/react-server-dom-webpack-client.node.production.min.js.map +1 -1
  13. package/cjs/react-server-dom-webpack-client.node.unbundled.development.js +181 -324
  14. package/cjs/react-server-dom-webpack-client.node.unbundled.production.js +151 -168
  15. package/cjs/react-server-dom-webpack-client.node.unbundled.production.min.js +30 -30
  16. package/cjs/react-server-dom-webpack-client.node.unbundled.production.min.js.map +1 -1
  17. package/cjs/react-server-dom-webpack-node-register.js.map +1 -1
  18. package/cjs/react-server-dom-webpack-plugin.js.map +1 -1
  19. package/cjs/react-server-dom-webpack-server.browser.development.js +424 -587
  20. package/cjs/react-server-dom-webpack-server.browser.production.js +368 -403
  21. package/cjs/react-server-dom-webpack-server.browser.production.min.js +68 -65
  22. package/cjs/react-server-dom-webpack-server.browser.production.min.js.map +1 -1
  23. package/cjs/react-server-dom-webpack-server.edge.development.js +424 -590
  24. package/cjs/react-server-dom-webpack-server.edge.production.js +369 -407
  25. package/cjs/react-server-dom-webpack-server.edge.production.min.js +69 -67
  26. package/cjs/react-server-dom-webpack-server.edge.production.min.js.map +1 -1
  27. package/cjs/react-server-dom-webpack-server.node.development.js +423 -586
  28. package/cjs/react-server-dom-webpack-server.node.production.js +368 -403
  29. package/cjs/react-server-dom-webpack-server.node.production.min.js +72 -70
  30. package/cjs/react-server-dom-webpack-server.node.production.min.js.map +1 -1
  31. package/cjs/react-server-dom-webpack-server.node.unbundled.development.js +423 -586
  32. package/cjs/react-server-dom-webpack-server.node.unbundled.production.js +368 -403
  33. package/cjs/react-server-dom-webpack-server.node.unbundled.production.min.js +69 -67
  34. package/cjs/react-server-dom-webpack-server.node.unbundled.production.min.js.map +1 -1
  35. package/package.json +11 -5
  36. package/umd/react-server-dom-webpack-client.browser.development.js +176 -272
  37. package/umd/react-server-dom-webpack-client.browser.production.min.js +23 -22
  38. package/umd/react-server-dom-webpack-server.browser.development.js +424 -587
  39. package/umd/react-server-dom-webpack-server.browser.production.min.js +52 -52
@@ -19,7 +19,7 @@ const enablePostpone = false;
19
19
  function scheduleWork(callback) {
20
20
  callback();
21
21
  }
22
- const VIEW_SIZE = 512;
22
+ const VIEW_SIZE = 2048;
23
23
  let currentView = null;
24
24
  let writtenBytes = 0;
25
25
  function beginWriting(destination) {
@@ -32,10 +32,9 @@ function writeChunk(destination, chunk) {
32
32
  }
33
33
 
34
34
  if (chunk.byteLength > VIEW_SIZE) {
35
+ // this chunk may overflow a single view which implies it was not
35
36
  // one that is cached by the streaming renderer. We will enqueu
36
37
  // it directly and expect it is not re-used
37
-
38
-
39
38
  if (writtenBytes > 0) {
40
39
  destination.enqueue(new Uint8Array(currentView.buffer, 0, writtenBytes));
41
40
  currentView = new Uint8Array(VIEW_SIZE);
@@ -110,10 +109,10 @@ function closeWithError(destination, error) {
110
109
  }
111
110
 
112
111
  // eslint-disable-next-line no-unused-vars
113
- const CLIENT_REFERENCE_TAG$1 = Symbol.for('react.client.reference');
112
+ const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
114
113
  const SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');
115
114
  function isClientReference(reference) {
116
- return reference.$$typeof === CLIENT_REFERENCE_TAG$1;
115
+ return reference.$$typeof === CLIENT_REFERENCE_TAG;
117
116
  }
118
117
  function isServerReference(reference) {
119
118
  return reference.$$typeof === SERVER_REFERENCE_TAG;
@@ -125,7 +124,7 @@ function registerClientReference(proxyImplementation, id, exportName) {
125
124
  function registerClientReferenceImpl(proxyImplementation, id, async) {
126
125
  return Object.defineProperties(proxyImplementation, {
127
126
  $$typeof: {
128
- value: CLIENT_REFERENCE_TAG$1
127
+ value: CLIENT_REFERENCE_TAG
129
128
  },
130
129
  $$id: {
131
130
  value: id
@@ -146,7 +145,6 @@ function bind() {
146
145
  const newFn = FunctionBind.apply(this, arguments);
147
146
 
148
147
  if (this.$$typeof === SERVER_REFERENCE_TAG) {
149
-
150
148
  const args = ArraySlice.call(arguments, 1);
151
149
  return Object.defineProperties(newFn, {
152
150
  $$typeof: {
@@ -173,16 +171,13 @@ function registerServerReference(reference, id, exportName) {
173
171
  value: SERVER_REFERENCE_TAG
174
172
  },
175
173
  $$id: {
176
- value: exportName === null ? id : id + '#' + exportName,
177
- configurable: true
174
+ value: exportName === null ? id : id + '#' + exportName
178
175
  },
179
176
  $$bound: {
180
- value: null,
181
- configurable: true
177
+ value: null
182
178
  },
183
179
  bind: {
184
- value: bind,
185
- configurable: true
180
+ value: bind
186
181
  }
187
182
  });
188
183
  }
@@ -221,10 +216,6 @@ const deepProxyHandlers = {
221
216
  // $FlowFixMe[prop-missing]
222
217
  return Object.prototype[Symbol.toPrimitive];
223
218
 
224
- case Symbol.toStringTag:
225
- // $FlowFixMe[prop-missing]
226
- return Object.prototype[Symbol.toStringTag];
227
-
228
219
  case 'Provider':
229
220
  throw new Error("Cannot render a Client Context Provider on the Server. " + "Instead, you can export a Client Component wrapper " + "that itself renders a Client Context Provider.");
230
221
  } // eslint-disable-next-line react-internal/safe-string-coercion
@@ -266,10 +257,6 @@ function getReference(target, name) {
266
257
  // $FlowFixMe[prop-missing]
267
258
  return Object.prototype[Symbol.toPrimitive];
268
259
 
269
- case Symbol.toStringTag:
270
- // $FlowFixMe[prop-missing]
271
- return Object.prototype[Symbol.toStringTag];
272
-
273
260
  case '__esModule':
274
261
  // Something is conditionally checking which export to use. We'll pretend to be
275
262
  // an ESM compat module but then we'll check again on the client.
@@ -310,10 +297,6 @@ function getReference(target, name) {
310
297
 
311
298
  }
312
299
 
313
- if (typeof name === 'symbol') {
314
- throw new Error('Cannot read Symbol exports. Only named exports are supported on a client module ' + 'imported on the server.');
315
- }
316
-
317
300
  let cachedReference = target[name];
318
301
 
319
302
  if (!cachedReference) {
@@ -408,9 +391,7 @@ function getServerReferenceBoundArguments(config, serverReference) {
408
391
 
409
392
  const ReactDOMSharedInternals = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
410
393
 
411
- const ReactDOMCurrentDispatcher = ReactDOMSharedInternals.ReactDOMCurrentDispatcher;
412
- const previousDispatcher = ReactDOMCurrentDispatcher.current;
413
- ReactDOMCurrentDispatcher.current = {
394
+ const ReactDOMFlightServerDispatcher = {
414
395
  prefetchDNS,
415
396
  preconnect,
416
397
  preload,
@@ -436,8 +417,6 @@ function prefetchDNS(href) {
436
417
 
437
418
  hints.add(key);
438
419
  emitHint(request, 'D', href);
439
- } else {
440
- previousDispatcher.prefetchDNS(href);
441
420
  }
442
421
  }
443
422
  }
@@ -464,8 +443,6 @@ function preconnect(href, crossOrigin) {
464
443
  } else {
465
444
  emitHint(request, 'C', href);
466
445
  }
467
- } else {
468
- previousDispatcher.preconnect(href, crossOrigin);
469
446
  }
470
447
  }
471
448
  }
@@ -499,8 +476,6 @@ function preload(href, as, options) {
499
476
  } else {
500
477
  emitHint(request, 'L', [href, as]);
501
478
  }
502
- } else {
503
- previousDispatcher.preload(href, as, options);
504
479
  }
505
480
  }
506
481
  }
@@ -528,8 +503,6 @@ function preloadModule$1(href, options) {
528
503
  } else {
529
504
  return emitHint(request, 'm', href);
530
505
  }
531
- } else {
532
- previousDispatcher.preloadModule(href, options);
533
506
  }
534
507
  }
535
508
  }
@@ -559,21 +532,19 @@ function preinitStyle(href, precedence, options) {
559
532
  } else {
560
533
  return emitHint(request, 'S', href);
561
534
  }
562
- } else {
563
- previousDispatcher.preinitStyle(href, precedence, options);
564
535
  }
565
536
  }
566
537
  }
567
538
  }
568
539
 
569
- function preinitScript(src, options) {
540
+ function preinitScript(href, options) {
570
541
  {
571
- if (typeof src === 'string') {
542
+ if (typeof href === 'string') {
572
543
  const request = resolveRequest();
573
544
 
574
545
  if (request) {
575
546
  const hints = getHints(request);
576
- const key = 'X|' + src;
547
+ const key = 'X|' + href;
577
548
 
578
549
  if (hints.has(key)) {
579
550
  // duplicate hint
@@ -584,25 +555,23 @@ function preinitScript(src, options) {
584
555
  const trimmed = trimOptions(options);
585
556
 
586
557
  if (trimmed) {
587
- return emitHint(request, 'X', [src, trimmed]);
558
+ return emitHint(request, 'X', [href, trimmed]);
588
559
  } else {
589
- return emitHint(request, 'X', src);
560
+ return emitHint(request, 'X', href);
590
561
  }
591
- } else {
592
- previousDispatcher.preinitScript(src, options);
593
562
  }
594
563
  }
595
564
  }
596
565
  }
597
566
 
598
- function preinitModuleScript(src, options) {
567
+ function preinitModuleScript(href, options) {
599
568
  {
600
- if (typeof src === 'string') {
569
+ if (typeof href === 'string') {
601
570
  const request = resolveRequest();
602
571
 
603
572
  if (request) {
604
573
  const hints = getHints(request);
605
- const key = 'M|' + src;
574
+ const key = 'M|' + href;
606
575
 
607
576
  if (hints.has(key)) {
608
577
  // duplicate hint
@@ -613,12 +582,10 @@ function preinitModuleScript(src, options) {
613
582
  const trimmed = trimOptions(options);
614
583
 
615
584
  if (trimmed) {
616
- return emitHint(request, 'M', [src, trimmed]);
585
+ return emitHint(request, 'M', [href, trimmed]);
617
586
  } else {
618
- return emitHint(request, 'M', src);
587
+ return emitHint(request, 'M', href);
619
588
  }
620
- } else {
621
- previousDispatcher.preinitModuleScript(src, options);
622
589
  }
623
590
  }
624
591
  }
@@ -660,7 +627,10 @@ function getImagePreloadKey(href, imageSrcSet, imageSizes) {
660
627
  return "[image]" + uniquePart;
661
628
  }
662
629
 
663
- // This module registers the host dispatcher so it needs to be imported
630
+ const ReactDOMCurrentDispatcher = ReactDOMSharedInternals.Dispatcher;
631
+ function prepareHostDispatcher() {
632
+ ReactDOMCurrentDispatcher.current = ReactDOMFlightServerDispatcher;
633
+ } // Used to distinguish these contexts from ones used in other renderers.
664
634
  // small, smaller than how we encode undefined, and is unambiguous. We could use
665
635
  // a different tuple structure to encode this instead but this makes the runtime
666
636
  // cost cheaper by eliminating a type checks in more positions.
@@ -670,16 +640,13 @@ function createHints() {
670
640
  return new Set();
671
641
  }
672
642
 
673
- const supportsRequestStorage = false;
674
- const requestStorage = null;
675
-
676
643
  // ATTENTION
677
644
  // When adding new symbols to this file,
678
645
  // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
679
646
  // The Symbol used to tag the ReactElement-like types.
680
647
  const REACT_ELEMENT_TYPE = Symbol.for('react.element');
681
648
  const REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
682
- const REACT_CONTEXT_TYPE = Symbol.for('react.context');
649
+ const REACT_SERVER_CONTEXT_TYPE = Symbol.for('react.server_context');
683
650
  const REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
684
651
  const REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
685
652
  const REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
@@ -703,6 +670,146 @@ function getIteratorFn(maybeIterable) {
703
670
  return null;
704
671
  }
705
672
 
673
+ // Forming a reverse tree.
674
+ // The structure of a context snapshot is an implementation of this file.
675
+ // Currently, it's implemented as tracking the current active node.
676
+
677
+
678
+ const rootContextSnapshot = null; // We assume that this runtime owns the "current" field on all ReactContext instances.
679
+ // This global (actually thread local) state represents what state all those "current",
680
+ // fields are currently in.
681
+
682
+ let currentActiveSnapshot = null;
683
+
684
+ function popNode(prev) {
685
+ {
686
+ prev.context._currentValue = prev.parentValue;
687
+ }
688
+ }
689
+
690
+ function pushNode(next) {
691
+ {
692
+ next.context._currentValue = next.value;
693
+ }
694
+ }
695
+
696
+ function popToNearestCommonAncestor(prev, next) {
697
+ if (prev === next) ; else {
698
+ popNode(prev);
699
+ const parentPrev = prev.parent;
700
+ const parentNext = next.parent;
701
+
702
+ if (parentPrev === null) {
703
+ if (parentNext !== null) {
704
+ throw new Error('The stacks must reach the root at the same time. This is a bug in React.');
705
+ }
706
+ } else {
707
+ if (parentNext === null) {
708
+ throw new Error('The stacks must reach the root at the same time. This is a bug in React.');
709
+ }
710
+
711
+ popToNearestCommonAncestor(parentPrev, parentNext); // On the way back, we push the new ones that weren't common.
712
+
713
+ pushNode(next);
714
+ }
715
+ }
716
+ }
717
+
718
+ function popAllPrevious(prev) {
719
+ popNode(prev);
720
+ const parentPrev = prev.parent;
721
+
722
+ if (parentPrev !== null) {
723
+ popAllPrevious(parentPrev);
724
+ }
725
+ }
726
+
727
+ function pushAllNext(next) {
728
+ const parentNext = next.parent;
729
+
730
+ if (parentNext !== null) {
731
+ pushAllNext(parentNext);
732
+ }
733
+
734
+ pushNode(next);
735
+ }
736
+
737
+ function popPreviousToCommonLevel(prev, next) {
738
+ popNode(prev);
739
+ const parentPrev = prev.parent;
740
+
741
+ if (parentPrev === null) {
742
+ throw new Error('The depth must equal at least at zero before reaching the root. This is a bug in React.');
743
+ }
744
+
745
+ if (parentPrev.depth === next.depth) {
746
+ // We found the same level. Now we just need to find a shared ancestor.
747
+ popToNearestCommonAncestor(parentPrev, next);
748
+ } else {
749
+ // We must still be deeper.
750
+ popPreviousToCommonLevel(parentPrev, next);
751
+ }
752
+ }
753
+
754
+ function popNextToCommonLevel(prev, next) {
755
+ const parentNext = next.parent;
756
+
757
+ if (parentNext === null) {
758
+ throw new Error('The depth must equal at least at zero before reaching the root. This is a bug in React.');
759
+ }
760
+
761
+ if (prev.depth === parentNext.depth) {
762
+ // We found the same level. Now we just need to find a shared ancestor.
763
+ popToNearestCommonAncestor(prev, parentNext);
764
+ } else {
765
+ // We must still be deeper.
766
+ popNextToCommonLevel(prev, parentNext);
767
+ }
768
+
769
+ pushNode(next);
770
+ } // Perform context switching to the new snapshot.
771
+ // To make it cheap to read many contexts, while not suspending, we make the switch eagerly by
772
+ // updating all the context's current values. That way reads, always just read the current value.
773
+ // At the cost of updating contexts even if they're never read by this subtree.
774
+
775
+
776
+ function switchContext(newSnapshot) {
777
+ // The basic algorithm we need to do is to pop back any contexts that are no longer on the stack.
778
+ // We also need to update any new contexts that are now on the stack with the deepest value.
779
+ // The easiest way to update new contexts is to just reapply them in reverse order from the
780
+ // perspective of the backpointers. To avoid allocating a lot when switching, we use the stack
781
+ // for that. Therefore this algorithm is recursive.
782
+ // 1) First we pop which ever snapshot tree was deepest. Popping old contexts as we go.
783
+ // 2) Then we find the nearest common ancestor from there. Popping old contexts as we go.
784
+ // 3) Then we reapply new contexts on the way back up the stack.
785
+ const prev = currentActiveSnapshot;
786
+ const next = newSnapshot;
787
+
788
+ if (prev !== next) {
789
+ if (prev === null) {
790
+ // $FlowFixMe[incompatible-call]: This has to be non-null since it's not equal to prev.
791
+ pushAllNext(next);
792
+ } else if (next === null) {
793
+ popAllPrevious(prev);
794
+ } else if (prev.depth === next.depth) {
795
+ popToNearestCommonAncestor(prev, next);
796
+ } else if (prev.depth > next.depth) {
797
+ popPreviousToCommonLevel(prev, next);
798
+ } else {
799
+ popNextToCommonLevel(prev, next);
800
+ }
801
+
802
+ currentActiveSnapshot = next;
803
+ }
804
+ }
805
+ function getActiveContext() {
806
+ return currentActiveSnapshot;
807
+ }
808
+ function readContext$1(context) {
809
+ const value = context._currentValue ;
810
+ return value;
811
+ }
812
+
706
813
  // Corresponds to ReactFiberWakeable and ReactFizzWakeable modules. Generally,
707
814
  // changes to one module should be reflected in the others.
708
815
  // TODO: Rename this module and the corresponding Fiber one to "Thenable"
@@ -831,13 +938,16 @@ function prepareToUseHooksForComponent(prevThenableState) {
831
938
  thenableState = prevThenableState;
832
939
  }
833
940
  function getThenableStateAfterSuspending() {
834
- // If you use() to Suspend this should always exist but if you throw a Promise instead,
835
- // which is not really supported anymore, it will be empty. We use the empty set as a
836
- // marker to know if this was a replay of the same component or first attempt.
837
- const state = thenableState || createThenableState();
941
+ const state = thenableState;
838
942
  thenableState = null;
839
943
  return state;
840
944
  }
945
+
946
+ function readContext(context) {
947
+
948
+ return readContext$1(context);
949
+ }
950
+
841
951
  const HooksDispatcher = {
842
952
  useMemo(nextCreate) {
843
953
  return nextCreate();
@@ -851,8 +961,8 @@ const HooksDispatcher = {
851
961
 
852
962
  useDeferredValue: unsupportedHook,
853
963
  useTransition: unsupportedHook,
854
- readContext: unsupportedContext,
855
- useContext: unsupportedContext,
964
+ readContext,
965
+ useContext: readContext,
856
966
  useReducer: unsupportedHook,
857
967
  useRef: unsupportedHook,
858
968
  useState: unsupportedHook,
@@ -888,10 +998,6 @@ function unsupportedRefresh() {
888
998
  throw new Error('Refreshing the cache is not supported in Server Components.');
889
999
  }
890
1000
 
891
- function unsupportedContext() {
892
- throw new Error('Cannot read a Client Context from a Server Component.');
893
- }
894
-
895
1001
  function useId() {
896
1002
  if (currentRequest$1 === null) {
897
1003
  throw new Error('useId can only be used while React is rendering');
@@ -917,22 +1023,14 @@ function use(usable) {
917
1023
  }
918
1024
 
919
1025
  return trackUsedThenable(thenableState, thenable, index);
920
- } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {
921
- unsupportedContext();
1026
+ } else if (usable.$$typeof === REACT_SERVER_CONTEXT_TYPE) {
1027
+ const context = usable;
1028
+ return readContext(context);
922
1029
  }
923
1030
  }
924
1031
 
925
- if (isClientReference(usable)) {
926
- if (usable.value != null && usable.value.$$typeof === REACT_CONTEXT_TYPE) {
927
- // Show a more specific message since it's a common mistake.
928
- throw new Error('Cannot read a Client Context from a Server Component.');
929
- } else {
930
- throw new Error('Cannot use() an already resolved Client Reference.');
931
- }
932
- } else {
933
- throw new Error( // eslint-disable-next-line react-internal/safe-string-coercion
934
- 'An unsupported type was passed to use(): ' + String(usable));
935
- }
1032
+
1033
+ throw new Error('An unsupported type was passed to use(): ' + String(usable));
936
1034
  }
937
1035
 
938
1036
  function createSignal() {
@@ -1011,10 +1109,6 @@ function describeValueForErrorMessage(value) {
1011
1109
  return '[...]';
1012
1110
  }
1013
1111
 
1014
- if (value !== null && value.$$typeof === CLIENT_REFERENCE_TAG) {
1015
- return describeClientReference();
1016
- }
1017
-
1018
1112
  const name = objectName(value);
1019
1113
 
1020
1114
  if (name === 'Object') {
@@ -1025,14 +1119,7 @@ function describeValueForErrorMessage(value) {
1025
1119
  }
1026
1120
 
1027
1121
  case 'function':
1028
- {
1029
- if (value.$$typeof === CLIENT_REFERENCE_TAG) {
1030
- return describeClientReference();
1031
- }
1032
-
1033
- const name = value.displayName || value.name;
1034
- return name ? 'function ' + name : 'function';
1035
- }
1122
+ return 'function';
1036
1123
 
1037
1124
  default:
1038
1125
  // eslint-disable-next-line react-internal/safe-string-coercion
@@ -1078,12 +1165,6 @@ function describeElementType(type) {
1078
1165
  return '';
1079
1166
  }
1080
1167
 
1081
- const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
1082
-
1083
- function describeClientReference(ref) {
1084
- return 'client';
1085
- }
1086
-
1087
1168
  function describeObjectForErrorMessage(objectOrArray, expandedName) {
1088
1169
  const objKind = objectName(objectOrArray);
1089
1170
 
@@ -1131,8 +1212,6 @@ function describeObjectForErrorMessage(objectOrArray, expandedName) {
1131
1212
  } else {
1132
1213
  if (objectOrArray.$$typeof === REACT_ELEMENT_TYPE) {
1133
1214
  str = '<' + describeElementType(objectOrArray.type) + '/>';
1134
- } else if (objectOrArray.$$typeof === CLIENT_REFERENCE_TAG) {
1135
- return describeClientReference();
1136
1215
  } else {
1137
1216
  // Print Object
1138
1217
  str = '{';
@@ -1212,11 +1291,12 @@ function defaultPostponeHandler(reason) {// Noop
1212
1291
  const OPEN = 0;
1213
1292
  const CLOSING = 1;
1214
1293
  const CLOSED = 2;
1215
- function createRequest(model, bundlerConfig, onError, identifierPrefix, onPostpone, environmentName) {
1294
+ function createRequest(model, bundlerConfig, onError, context, identifierPrefix, onPostpone) {
1216
1295
  if (ReactCurrentCache.current !== null && ReactCurrentCache.current !== DefaultCacheDispatcher) {
1217
1296
  throw new Error('Currently React only supports one RSC renderer at a time.');
1218
1297
  }
1219
1298
 
1299
+ prepareHostDispatcher();
1220
1300
  ReactCurrentCache.current = DefaultCacheDispatcher;
1221
1301
  const abortSet = new Set();
1222
1302
  const pingedTasks = [];
@@ -1242,15 +1322,21 @@ function createRequest(model, bundlerConfig, onError, identifierPrefix, onPostpo
1242
1322
  writtenSymbols: new Map(),
1243
1323
  writtenClientReferences: new Map(),
1244
1324
  writtenServerReferences: new Map(),
1325
+ writtenProviders: new Map(),
1245
1326
  writtenObjects: new WeakMap(),
1246
1327
  identifierPrefix: identifierPrefix || '',
1247
1328
  identifierCount: 1,
1248
1329
  taintCleanupQueue: cleanupQueue,
1249
1330
  onError: onError === undefined ? defaultErrorHandler : onError,
1250
- onPostpone: onPostpone === undefined ? defaultPostponeHandler : onPostpone
1331
+ onPostpone: onPostpone === undefined ? defaultPostponeHandler : onPostpone,
1332
+ // $FlowFixMe[missing-this-annot]
1333
+ toJSON: function (key, value) {
1334
+ return resolveModelToJSON(request, this, key, value);
1335
+ }
1251
1336
  };
1252
-
1253
- const rootTask = createTask(request, model, null, false, abortSet);
1337
+ request.pendingChunks++;
1338
+ const rootContext = createRootContext();
1339
+ const rootTask = createTask(request, model, rootContext, abortSet);
1254
1340
  pingedTasks.push(rootTask);
1255
1341
  return request;
1256
1342
  }
@@ -1261,9 +1347,13 @@ function resolveRequest() {
1261
1347
  return null;
1262
1348
  }
1263
1349
 
1264
- function serializeThenable(request, task, thenable) {
1265
- const newTask = createTask(request, null, task.keyPath, // the server component sequence continues through Promise-as-a-child.
1266
- task.implicitSlot, request.abortableTasks);
1350
+ function createRootContext(reqContext) {
1351
+ return importServerContexts();
1352
+ }
1353
+
1354
+ function serializeThenable(request, thenable) {
1355
+ request.pendingChunks++;
1356
+ const newTask = createTask(request, null, getActiveContext(), request.abortableTasks);
1267
1357
 
1268
1358
  switch (thenable.status) {
1269
1359
  case 'fulfilled':
@@ -1397,117 +1487,61 @@ function createLazyWrapperAroundWakeable(wakeable) {
1397
1487
  _payload: thenable,
1398
1488
  _init: readThenable
1399
1489
  };
1400
-
1401
1490
  return lazyType;
1402
1491
  }
1403
1492
 
1404
- function renderFunctionComponent(request, task, key, Component, props) {
1405
- // Reset the task's thenable state before continuing, so that if a later
1406
- // component suspends we can reuse the same task object. If the same
1407
- // component suspends again, the thenable state will be restored.
1408
- const prevThenableState = task.thenableState;
1409
- task.thenableState = null;
1410
-
1411
- prepareToUseHooksForComponent(prevThenableState); // The secondArg is always undefined in Server Components since refs error early.
1412
-
1413
- const secondArg = undefined;
1414
- let result = Component(props, secondArg);
1415
-
1416
- if (typeof result === 'object' && result !== null && typeof result.then === 'function') {
1417
- // When the return value is in children position we can resolve it immediately,
1418
- // to its value without a wrapper if it's synchronously available.
1419
- const thenable = result;
1420
-
1421
- if (thenable.status === 'fulfilled') {
1422
- return thenable.value;
1423
- } // TODO: Once we accept Promises as children on the client, we can just return
1424
- // the thenable here.
1425
-
1426
-
1427
- result = createLazyWrapperAroundWakeable(result);
1428
- } // Track this element's key on the Server Component on the keyPath context..
1429
-
1430
-
1431
- const prevKeyPath = task.keyPath;
1432
- const prevImplicitSlot = task.implicitSlot;
1433
-
1434
- if (key !== null) {
1435
- // Append the key to the path. Technically a null key should really add the child
1436
- // index. We don't do that to hold the payload small and implementation simple.
1437
- task.keyPath = prevKeyPath === null ? key : prevKeyPath + ',' + key;
1438
- } else if (prevKeyPath === null) {
1439
- // This sequence of Server Components has no keys. This means that it was rendered
1440
- // in a slot that needs to assign an implicit key. Even if children below have
1441
- // explicit keys, they should not be used for the outer most key since it might
1442
- // collide with other slots in that set.
1443
- task.implicitSlot = true;
1444
- }
1445
-
1446
- const json = renderModelDestructive(request, task, emptyRoot, '', result);
1447
- task.keyPath = prevKeyPath;
1448
- task.implicitSlot = prevImplicitSlot;
1449
- return json;
1450
- }
1451
-
1452
- function renderFragment(request, task, children) {
1453
-
1454
- {
1455
- return children;
1456
- }
1457
- }
1458
-
1459
- function renderClientElement(task, type, key, props) {
1460
- {
1461
- return [REACT_ELEMENT_TYPE, type, key, props];
1462
- } // We prepend the terminal client element that actually gets serialized with
1463
- } // The chunk ID we're currently rendering that we can assign debug data to.
1464
-
1465
-
1466
- let debugID = null;
1467
-
1468
- function renderElement(request, task, type, key, ref, props) {
1493
+ function attemptResolveElement(request, type, key, ref, props, prevThenableState) {
1469
1494
  if (ref !== null && ref !== undefined) {
1470
1495
  // When the ref moves to the regular props object this will implicitly
1471
1496
  // throw for functions. We could probably relax it to a DEV warning for other
1472
1497
  // cases.
1473
- // TODO: `ref` is now just a prop when `enableRefAsProp` is on. Should we
1474
- // do what the above comment says?
1475
1498
  throw new Error('Refs cannot be used in Server Components, nor passed to Client Components.');
1476
1499
  }
1477
1500
 
1478
1501
  if (typeof type === 'function') {
1479
1502
  if (isClientReference(type)) {
1480
1503
  // This is a reference to a Client Component.
1481
- return renderClientElement(task, type, key, props);
1482
- } // This is a Server Component.
1504
+ return [REACT_ELEMENT_TYPE, type, key, props];
1505
+ } // This is a server-side component.
1506
+
1507
+
1508
+ prepareToUseHooksForComponent(prevThenableState);
1509
+ const result = type(props);
1510
+
1511
+ if (typeof result === 'object' && result !== null && typeof result.then === 'function') {
1512
+ // When the return value is in children position we can resolve it immediately,
1513
+ // to its value without a wrapper if it's synchronously available.
1514
+ const thenable = result;
1483
1515
 
1516
+ if (thenable.status === 'fulfilled') {
1517
+ return thenable.value;
1518
+ } // TODO: Once we accept Promises as children on the client, we can just return
1519
+ // the thenable here.
1520
+
1521
+
1522
+ return createLazyWrapperAroundWakeable(result);
1523
+ }
1484
1524
 
1485
- return renderFunctionComponent(request, task, key, type, props);
1525
+ return result;
1486
1526
  } else if (typeof type === 'string') {
1487
1527
  // This is a host element. E.g. HTML.
1488
- return renderClientElement(task, type, key, props);
1528
+ return [REACT_ELEMENT_TYPE, type, key, props];
1489
1529
  } else if (typeof type === 'symbol') {
1490
- if (type === REACT_FRAGMENT_TYPE && key === null) {
1530
+ if (type === REACT_FRAGMENT_TYPE) {
1491
1531
  // For key-less fragments, we add a small optimization to avoid serializing
1492
1532
  // it as a wrapper.
1493
- const prevImplicitSlot = task.implicitSlot;
1494
-
1495
- if (task.keyPath === null) {
1496
- task.implicitSlot = true;
1497
- }
1498
-
1499
- const json = renderModelDestructive(request, task, emptyRoot, '', props.children);
1500
- task.implicitSlot = prevImplicitSlot;
1501
- return json;
1533
+ // TODO: If a key is specified, we should propagate its key to any children.
1534
+ // Same as if a Server Component has a key.
1535
+ return props.children;
1502
1536
  } // This might be a built-in React component. We'll let the client decide.
1503
1537
  // Any built-in works as long as its props are serializable.
1504
1538
 
1505
1539
 
1506
- return renderClientElement(task, type, key, props);
1540
+ return [REACT_ELEMENT_TYPE, type, key, props];
1507
1541
  } else if (type != null && typeof type === 'object') {
1508
1542
  if (isClientReference(type)) {
1509
1543
  // This is a reference to a Client Component.
1510
- return renderClientElement(task, type, key, props);
1544
+ return [REACT_ELEMENT_TYPE, type, key, props];
1511
1545
  }
1512
1546
 
1513
1547
  switch (type.$$typeof) {
@@ -1516,17 +1550,19 @@ function renderElement(request, task, type, key, ref, props) {
1516
1550
  const payload = type._payload;
1517
1551
  const init = type._init;
1518
1552
  const wrappedType = init(payload);
1519
- return renderElement(request, task, wrappedType, key, ref, props);
1553
+ return attemptResolveElement(request, wrappedType, key, ref, props, prevThenableState);
1520
1554
  }
1521
1555
 
1522
1556
  case REACT_FORWARD_REF_TYPE:
1523
1557
  {
1524
- return renderFunctionComponent(request, task, key, type.render, props);
1558
+ const render = type.render;
1559
+ prepareToUseHooksForComponent(prevThenableState);
1560
+ return render(props, undefined);
1525
1561
  }
1526
1562
 
1527
1563
  case REACT_MEMO_TYPE:
1528
1564
  {
1529
- return renderElement(request, task, type.type, key, ref, props);
1565
+ return attemptResolveElement(request, type.type, key, ref, props, prevThenableState);
1530
1566
  }
1531
1567
  }
1532
1568
  }
@@ -1544,30 +1580,14 @@ function pingTask(request, task) {
1544
1580
  }
1545
1581
  }
1546
1582
 
1547
- function createTask(request, model, keyPath, implicitSlot, abortSet) {
1548
- request.pendingChunks++;
1583
+ function createTask(request, model, context, abortSet) {
1549
1584
  const id = request.nextChunkId++;
1550
-
1551
- if (typeof model === 'object' && model !== null) {
1552
- // If we're about to write this into a new task we can assign it an ID early so that
1553
- // any other references can refer to the value we're about to write.
1554
- {
1555
- request.writtenObjects.set(model, id);
1556
- }
1557
- }
1558
-
1559
1585
  const task = {
1560
1586
  id,
1561
1587
  status: PENDING$1,
1562
1588
  model,
1563
- keyPath,
1564
- implicitSlot,
1589
+ context,
1565
1590
  ping: () => pingTask(request, task),
1566
- toJSON: function (parentPropertyName, value) {
1567
- const parent = this; // Make sure that `parent[parentPropertyName]` wasn't JSONified before `value` was passed to us
1568
-
1569
- return renderModel(request, task, parent, parentPropertyName, value);
1570
- },
1571
1591
  thenableState: null
1572
1592
  };
1573
1593
  abortSet.add(task);
@@ -1636,13 +1656,13 @@ function encodeReferenceChunk(request, id, reference) {
1636
1656
  return stringToChunk(row);
1637
1657
  }
1638
1658
 
1639
- function serializeClientReference(request, parent, parentPropertyName, clientReference) {
1659
+ function serializeClientReference(request, parent, key, clientReference) {
1640
1660
  const clientReferenceKey = getClientReferenceKey(clientReference);
1641
1661
  const writtenClientReferences = request.writtenClientReferences;
1642
1662
  const existingId = writtenClientReferences.get(clientReferenceKey);
1643
1663
 
1644
1664
  if (existingId !== undefined) {
1645
- if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {
1665
+ if (parent[0] === REACT_ELEMENT_TYPE && key === '1') {
1646
1666
  // If we're encoding the "type" of an element, we can refer
1647
1667
  // to that by a lazy reference instead of directly since React
1648
1668
  // knows how to deal with lazy values. This lets us suspend
@@ -1661,7 +1681,7 @@ function serializeClientReference(request, parent, parentPropertyName, clientRef
1661
1681
  emitImportChunk(request, importId, clientReferenceMetadata);
1662
1682
  writtenClientReferences.set(clientReferenceKey, importId);
1663
1683
 
1664
- if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {
1684
+ if (parent[0] === REACT_ELEMENT_TYPE && key === '1') {
1665
1685
  // If we're encoding the "type" of an element, we can refer
1666
1686
  // to that by a lazy reference instead of directly since React
1667
1687
  // knows how to deal with lazy values. This lets us suspend
@@ -1681,14 +1701,13 @@ function serializeClientReference(request, parent, parentPropertyName, clientRef
1681
1701
  }
1682
1702
 
1683
1703
  function outlineModel(request, value) {
1684
- const newTask = createTask(request, value, null, // The way we use outlining is for reusing an object.
1685
- false, // It makes no sense for that use case to be contextual.
1686
- request.abortableTasks);
1704
+ request.pendingChunks++;
1705
+ const newTask = createTask(request, value, getActiveContext(), request.abortableTasks);
1687
1706
  retryTask(request, newTask);
1688
1707
  return newTask.id;
1689
1708
  }
1690
1709
 
1691
- function serializeServerReference(request, serverReference) {
1710
+ function serializeServerReference(request, parent, key, serverReference) {
1692
1711
  const writtenServerReferences = request.writtenServerReferences;
1693
1712
  const existingId = writtenServerReferences.get(serverReference);
1694
1713
 
@@ -1768,77 +1787,91 @@ function escapeStringValue(value) {
1768
1787
  return value;
1769
1788
  }
1770
1789
  }
1771
-
1772
1790
  let modelRoot = false;
1773
1791
 
1774
- function renderModel(request, task, parent, key, value) {
1775
- const prevKeyPath = task.keyPath;
1776
- const prevImplicitSlot = task.implicitSlot;
1792
+ function resolveModelToJSON(request, parent, key, value) {
1777
1793
 
1778
- try {
1779
- return renderModelDestructive(request, task, parent, key, value);
1780
- } catch (thrownValue) {
1781
- const x = thrownValue === SuspenseException ? // This is a special type of exception used for Suspense. For historical
1782
- // reasons, the rest of the Suspense implementation expects the thrown
1783
- // value to be a thenable, because before `use` existed that was the
1784
- // (unstable) API for suspending. This implementation detail can change
1785
- // later, once we deprecate the old API in favor of `use`.
1786
- getSuspendedThenable() : thrownValue; // If the suspended/errored value was an element or lazy it can be reduced
1787
- // to a lazy reference, so that it doesn't error the parent.
1788
1794
 
1789
- const model = task.model;
1790
- const wasReactNode = typeof model === 'object' && model !== null && (model.$$typeof === REACT_ELEMENT_TYPE || model.$$typeof === REACT_LAZY_TYPE);
1795
+ switch (value) {
1796
+ case REACT_ELEMENT_TYPE:
1797
+ return '$';
1798
+ }
1791
1799
 
1792
- if (typeof x === 'object' && x !== null) {
1793
- // $FlowFixMe[method-unbinding]
1794
- if (typeof x.then === 'function') {
1795
- // Something suspended, we'll need to create a new task and resolve it later.
1796
- const newTask = createTask(request, task.model, task.keyPath, task.implicitSlot, request.abortableTasks);
1797
- const ping = newTask.ping;
1798
- x.then(ping, ping);
1799
- newTask.thenableState = getThenableStateAfterSuspending(); // Restore the context. We assume that this will be restored by the inner
1800
- // functions in case nothing throws so we don't use "finally" here.
1801
1800
 
1802
- task.keyPath = prevKeyPath;
1803
- task.implicitSlot = prevImplicitSlot;
1801
+ while (typeof value === 'object' && value !== null && (value.$$typeof === REACT_ELEMENT_TYPE || value.$$typeof === REACT_LAZY_TYPE)) {
1804
1802
 
1805
- if (wasReactNode) {
1806
- return serializeLazyID(newTask.id);
1807
- }
1803
+ try {
1804
+ switch (value.$$typeof) {
1805
+ case REACT_ELEMENT_TYPE:
1806
+ {
1807
+ const writtenObjects = request.writtenObjects;
1808
+ const existingId = writtenObjects.get(value);
1809
+
1810
+ if (existingId !== undefined) {
1811
+ if (existingId === -1) {
1812
+ // Seen but not yet outlined.
1813
+ const newId = outlineModel(request, value);
1814
+ return serializeByValueID(newId);
1815
+ } else if (modelRoot === value) {
1816
+ // This is the ID we're currently emitting so we need to write it
1817
+ // once but if we discover it again, we refer to it by id.
1818
+ modelRoot = null;
1819
+ } else {
1820
+ // We've already emitted this as an outlined object, so we can
1821
+ // just refer to that by its existing ID.
1822
+ return serializeByValueID(existingId);
1823
+ }
1824
+ } else {
1825
+ // This is the first time we've seen this object. We may never see it again
1826
+ // so we'll inline it. Mark it as seen. If we see it again, we'll outline.
1827
+ writtenObjects.set(value, -1);
1828
+ } // TODO: Concatenate keys of parents onto children.
1808
1829
 
1809
- return serializeByValueID(newTask.id);
1810
- }
1811
- } // Restore the context. We assume that this will be restored by the inner
1812
- // functions in case nothing throws so we don't use "finally" here.
1813
1830
 
1831
+ const element = value; // Attempt to render the Server Component.
1814
1832
 
1815
- task.keyPath = prevKeyPath;
1816
- task.implicitSlot = prevImplicitSlot;
1833
+ value = attemptResolveElement(request, element.type, element.key, element.ref, element.props, null);
1834
+ break;
1835
+ }
1817
1836
 
1818
- if (wasReactNode) {
1819
- // Something errored. We'll still send everything we have up until this point.
1837
+ case REACT_LAZY_TYPE:
1838
+ {
1839
+ const payload = value._payload;
1840
+ const init = value._init;
1841
+ value = init(payload);
1842
+ break;
1843
+ }
1844
+ }
1845
+ } catch (thrownValue) {
1846
+ const x = thrownValue === SuspenseException ? // This is a special type of exception used for Suspense. For historical
1847
+ // reasons, the rest of the Suspense implementation expects the thrown
1848
+ // value to be a thenable, because before `use` existed that was the
1849
+ // (unstable) API for suspending. This implementation detail can change
1850
+ // later, once we deprecate the old API in favor of `use`.
1851
+ getSuspendedThenable() : thrownValue;
1852
+
1853
+ if (typeof x === 'object' && x !== null) {
1854
+ // $FlowFixMe[method-unbinding]
1855
+ if (typeof x.then === 'function') {
1856
+ // Something suspended, we'll need to create a new task and resolve it later.
1857
+ request.pendingChunks++;
1858
+ const newTask = createTask(request, value, getActiveContext(), request.abortableTasks);
1859
+ const ping = newTask.ping;
1860
+ x.then(ping, ping);
1861
+ newTask.thenableState = getThenableStateAfterSuspending();
1862
+ return serializeLazyID(newTask.id);
1863
+ }
1864
+ } // Something errored. We'll still send everything we have up until this point.
1820
1865
  // We'll replace this element with a lazy reference that throws on the client
1821
1866
  // once it gets rendered.
1867
+
1868
+
1822
1869
  request.pendingChunks++;
1823
1870
  const errorId = request.nextChunkId++;
1824
1871
  const digest = logRecoverableError(request, x);
1825
1872
  emitErrorChunk(request, errorId, digest);
1826
1873
  return serializeLazyID(errorId);
1827
- } // Something errored but it was not in a React Node. There's no need to serialize
1828
- // it by value because it'll just error the whole parent row anyway so we can
1829
- // just stop any siblings and error the whole parent row.
1830
-
1831
-
1832
- throw x;
1833
- }
1834
- }
1835
-
1836
- function renderModelDestructive(request, task, parent, parentPropertyName, value) {
1837
- // Set the currently rendering model
1838
- task.model = value; // Special Symbol, that's very common.
1839
-
1840
- if (value === REACT_ELEMENT_TYPE) {
1841
- return '$';
1874
+ }
1842
1875
  }
1843
1876
 
1844
1877
  if (value === null) {
@@ -1846,70 +1879,9 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1846
1879
  }
1847
1880
 
1848
1881
  if (typeof value === 'object') {
1849
- switch (value.$$typeof) {
1850
- case REACT_ELEMENT_TYPE:
1851
- {
1852
- const writtenObjects = request.writtenObjects;
1853
- const existingId = writtenObjects.get(value);
1854
-
1855
- if (existingId !== undefined) {
1856
- if (modelRoot === value) {
1857
- // This is the ID we're currently emitting so we need to write it
1858
- // once but if we discover it again, we refer to it by id.
1859
- modelRoot = null;
1860
- } else if (existingId === -1) {
1861
- // Seen but not yet outlined.
1862
- // TODO: If we throw here we can treat this as suspending which causes an outline
1863
- // but that is able to reuse the same task if we're already in one but then that
1864
- // will be a lazy future value rather than guaranteed to exist but maybe that's good.
1865
- const newId = outlineModel(request, value);
1866
- return serializeByValueID(newId);
1867
- } else {
1868
- // We've already emitted this as an outlined object, so we can refer to that by its
1869
- // existing ID. TODO: We should use a lazy reference since, unlike plain objects,
1870
- // elements might suspend so it might not have emitted yet even if we have the ID for
1871
- // it. However, this creates an extra wrapper when it's not needed. We should really
1872
- // detect whether this already was emitted and synchronously available. In that
1873
- // case we can refer to it synchronously and only make it lazy otherwise.
1874
- // We currently don't have a data structure that lets us see that though.
1875
- return serializeByValueID(existingId);
1876
- }
1877
- } else {
1878
- // This is the first time we've seen this object. We may never see it again
1879
- // so we'll inline it. Mark it as seen. If we see it again, we'll outline.
1880
- writtenObjects.set(value, -1);
1881
- }
1882
-
1883
- const element = value;
1884
-
1885
- const props = element.props;
1886
- let ref;
1887
-
1888
- {
1889
- ref = element.ref;
1890
- } // Attempt to render the Server Component.
1891
-
1892
-
1893
- return renderElement(request, task, element.type, // $FlowFixMe[incompatible-call] the key of an element is null | string
1894
- element.key, ref, props);
1895
- }
1896
-
1897
- case REACT_LAZY_TYPE:
1898
- {
1899
- // Reset the task's thenable state before continuing. If there was one, it was
1900
- // from suspending the lazy before.
1901
- task.thenableState = null;
1902
- const lazy = value;
1903
- const payload = lazy._payload;
1904
- const init = lazy._init;
1905
- const resolvedModel = init(payload);
1906
-
1907
- return renderModelDestructive(request, task, emptyRoot, '', resolvedModel);
1908
- }
1909
- }
1910
1882
 
1911
1883
  if (isClientReference(value)) {
1912
- return serializeClientReference(request, parent, parentPropertyName, value);
1884
+ return serializeClientReference(request, parent, key, value);
1913
1885
  }
1914
1886
 
1915
1887
  const writtenObjects = request.writtenObjects;
@@ -1929,20 +1901,20 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1929
1901
  // or a Promise type. Either of which can be represented by a Promise.
1930
1902
 
1931
1903
 
1932
- const promiseId = serializeThenable(request, task, value);
1904
+ const promiseId = serializeThenable(request, value);
1933
1905
  writtenObjects.set(value, promiseId);
1934
1906
  return serializePromiseID(promiseId);
1935
1907
  }
1936
1908
 
1937
1909
  if (existingId !== undefined) {
1938
- if (modelRoot === value) {
1939
- // This is the ID we're currently emitting so we need to write it
1940
- // once but if we discover it again, we refer to it by id.
1941
- modelRoot = null;
1942
- } else if (existingId === -1) {
1910
+ if (existingId === -1) {
1943
1911
  // Seen but not yet outlined.
1944
1912
  const newId = outlineModel(request, value);
1945
1913
  return serializeByValueID(newId);
1914
+ } else if (modelRoot === value) {
1915
+ // This is the ID we're currently emitting so we need to write it
1916
+ // once but if we discover it again, we refer to it by id.
1917
+ modelRoot = null;
1946
1918
  } else {
1947
1919
  // We've already emitted this as an outlined object, so we can
1948
1920
  // just refer to that by its existing ID.
@@ -1955,7 +1927,8 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1955
1927
  }
1956
1928
 
1957
1929
  if (isArray(value)) {
1958
- return renderFragment(request, task, value);
1930
+ // $FlowFixMe[incompatible-return]
1931
+ return value;
1959
1932
  }
1960
1933
 
1961
1934
  if (value instanceof Map) {
@@ -1969,7 +1942,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1969
1942
  const iteratorFn = getIteratorFn(value);
1970
1943
 
1971
1944
  if (iteratorFn) {
1972
- return renderFragment(request, task, Array.from(value));
1945
+ return Array.from(value);
1973
1946
  } // Verify that this is a simple plain object.
1974
1947
 
1975
1948
 
@@ -1989,7 +1962,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1989
1962
  if (value[value.length - 1] === 'Z') {
1990
1963
  // Possibly a Date, whose toJSON automatically calls toISOString
1991
1964
  // $FlowFixMe[incompatible-use]
1992
- const originalValue = parent[parentPropertyName];
1965
+ const originalValue = parent[key];
1993
1966
 
1994
1967
  if (originalValue instanceof Date) {
1995
1968
  return serializeDateFromDateJSON(value);
@@ -2019,18 +1992,19 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2019
1992
  }
2020
1993
 
2021
1994
  if (typeof value === 'function') {
1995
+
2022
1996
  if (isClientReference(value)) {
2023
- return serializeClientReference(request, parent, parentPropertyName, value);
1997
+ return serializeClientReference(request, parent, key, value);
2024
1998
  }
2025
1999
 
2026
2000
  if (isServerReference(value)) {
2027
- return serializeServerReference(request, value);
2001
+ return serializeServerReference(request, parent, key, value);
2028
2002
  }
2029
2003
 
2030
- if (/^on[A-Z]/.test(parentPropertyName)) {
2031
- throw new Error('Event handlers cannot be passed to Client Component props.' + describeObjectForErrorMessage(parent, parentPropertyName) + '\nIf you need interactivity, consider converting part of this to a Client Component.');
2004
+ if (/^on[A-Z]/.test(key)) {
2005
+ throw new Error('Event handlers cannot be passed to Client Component props.' + describeObjectForErrorMessage(parent, key) + '\nIf you need interactivity, consider converting part of this to a Client Component.');
2032
2006
  } else {
2033
- throw new Error('Functions cannot be passed directly to Client Components ' + 'unless you explicitly expose it by marking it with "use server". ' + 'Or maybe you meant to call this function rather than return it.' + describeObjectForErrorMessage(parent, parentPropertyName));
2007
+ throw new Error('Functions cannot be passed directly to Client Components ' + 'unless you explicitly expose it by marking it with "use server".' + describeObjectForErrorMessage(parent, key));
2034
2008
  }
2035
2009
  }
2036
2010
 
@@ -2047,7 +2021,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2047
2021
 
2048
2022
  if (Symbol.for(name) !== value) {
2049
2023
  throw new Error('Only global symbols received from Symbol.for(...) can be passed to Client Components. ' + ("The symbol Symbol.for(" + // $FlowFixMe[incompatible-type] `description` might be undefined
2050
- value.description + ") cannot be found among global symbols.") + describeObjectForErrorMessage(parent, parentPropertyName));
2024
+ value.description + ") cannot be found among global symbols.") + describeObjectForErrorMessage(parent, key));
2051
2025
  }
2052
2026
 
2053
2027
  request.pendingChunks++;
@@ -2062,38 +2036,17 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2062
2036
  return serializeBigInt(value);
2063
2037
  }
2064
2038
 
2065
- throw new Error("Type " + typeof value + " is not supported in Client Component props." + describeObjectForErrorMessage(parent, parentPropertyName));
2039
+ throw new Error("Type " + typeof value + " is not supported in Client Component props." + describeObjectForErrorMessage(parent, key));
2066
2040
  }
2067
2041
 
2068
2042
  function logPostpone(request, reason) {
2069
- const prevRequest = currentRequest;
2070
- currentRequest = null;
2071
-
2072
- try {
2073
- const onPostpone = request.onPostpone;
2074
-
2075
- if (supportsRequestStorage) ; else {
2076
- onPostpone(reason);
2077
- }
2078
- } finally {
2079
- currentRequest = prevRequest;
2080
- }
2043
+ const onPostpone = request.onPostpone;
2044
+ onPostpone(reason);
2081
2045
  }
2082
2046
 
2083
2047
  function logRecoverableError(request, error) {
2084
- const prevRequest = currentRequest;
2085
- currentRequest = null;
2086
- let errorDigest;
2087
-
2088
- try {
2089
- const onError = request.onError;
2090
-
2091
- if (supportsRequestStorage) ; else {
2092
- errorDigest = onError(error);
2093
- }
2094
- } finally {
2095
- currentRequest = prevRequest;
2096
- }
2048
+ const onError = request.onError;
2049
+ const errorDigest = onError(error);
2097
2050
 
2098
2051
  if (errorDigest != null && typeof errorDigest !== 'string') {
2099
2052
  // eslint-disable-next-line react-internal/prod-error-codes
@@ -2163,54 +2116,62 @@ function emitSymbolChunk(request, id, name) {
2163
2116
  request.completedImportChunks.push(processedChunk);
2164
2117
  }
2165
2118
 
2166
- function emitModelChunk(request, id, json) {
2119
+ function emitModelChunk(request, id, model) {
2120
+ // Track the root so we know that we have to emit this object even though it
2121
+ // already has an ID. This is needed because we might see this object twice
2122
+ // in the same toJSON if it is cyclic.
2123
+ modelRoot = model; // $FlowFixMe[incompatible-type] stringify can return null
2124
+
2125
+ const json = stringify(model, request.toJSON);
2167
2126
  const row = id.toString(16) + ':' + json + '\n';
2168
2127
  const processedChunk = stringToChunk(row);
2169
2128
  request.completedRegularChunks.push(processedChunk);
2170
2129
  }
2171
2130
 
2172
- const emptyRoot = {};
2173
-
2174
2131
  function retryTask(request, task) {
2175
2132
  if (task.status !== PENDING$1) {
2176
2133
  // We completed this by other means before we had a chance to retry it.
2177
2134
  return;
2178
2135
  }
2179
2136
 
2137
+ switchContext(task.context);
2138
+
2180
2139
  try {
2181
- // Track the root so we know that we have to emit this object even though it
2182
- // already has an ID. This is needed because we might see this object twice
2183
- // in the same toJSON if it is cyclic.
2184
- modelRoot = task.model;
2140
+ let value = task.model;
2185
2141
 
2186
- if (false) ; // We call the destructive form that mutates this task. That way if something
2187
- // suspends again, we can reuse the same task instead of spawning a new one.
2142
+ if (typeof value === 'object' && value !== null && value.$$typeof === REACT_ELEMENT_TYPE) {
2143
+ request.writtenObjects.set(value, task.id); // TODO: Concatenate keys of parents onto children.
2188
2144
 
2145
+ const element = value; // When retrying a component, reuse the thenableState from the
2146
+ // previous attempt.
2189
2147
 
2190
- const resolvedModel = renderModelDestructive(request, task, emptyRoot, '', task.model);
2148
+ const prevThenableState = task.thenableState; // Attempt to render the Server Component.
2149
+ // Doing this here lets us reuse this same task if the next component
2150
+ // also suspends.
2191
2151
 
2192
- if (false) ; // Track the root again for the resolved object.
2152
+ task.model = value;
2153
+ value = attemptResolveElement(request, element.type, element.key, element.ref, element.props, prevThenableState); // Successfully finished this component. We're going to keep rendering
2154
+ // using the same task, but we reset its thenable state before continuing.
2193
2155
 
2156
+ task.thenableState = null; // Keep rendering and reuse the same task. This inner loop is separate
2157
+ // from the render above because we don't need to reset the thenable state
2158
+ // until the next time something suspends and retries.
2194
2159
 
2195
- modelRoot = resolvedModel; // The keyPath resets at any terminal child node.
2160
+ while (typeof value === 'object' && value !== null && value.$$typeof === REACT_ELEMENT_TYPE) {
2161
+ request.writtenObjects.set(value, task.id); // TODO: Concatenate keys of parents onto children.
2196
2162
 
2197
- task.keyPath = null;
2198
- task.implicitSlot = false;
2199
- let json;
2163
+ const nextElement = value;
2164
+ task.model = value;
2165
+ value = attemptResolveElement(request, nextElement.type, nextElement.key, nextElement.ref, nextElement.props, null);
2166
+ }
2167
+ } // Track that this object is outlined and has an id.
2200
2168
 
2201
- if (typeof resolvedModel === 'object' && resolvedModel !== null) {
2202
- // Object might contain unresolved values like additional elements.
2203
- // This is simulating what the JSON loop would do if this was part of it.
2204
- // $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do
2205
- json = stringify(resolvedModel, task.toJSON);
2206
- } else {
2207
- // If the value is a string, it means it's a terminal value and we already escaped it
2208
- // We don't need to escape it again so it's not passed the toJSON replacer.
2209
- // $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do
2210
- json = stringify(resolvedModel);
2169
+
2170
+ if (typeof value === 'object' && value !== null) {
2171
+ request.writtenObjects.set(value, task.id);
2211
2172
  }
2212
2173
 
2213
- emitModelChunk(request, task.id, json);
2174
+ emitModelChunk(request, task.id, value);
2214
2175
  request.abortableTasks.delete(task);
2215
2176
  task.status = COMPLETED;
2216
2177
  } catch (thrownValue) {
@@ -2236,7 +2197,6 @@ function retryTask(request, task) {
2236
2197
  task.status = ERRORED$1;
2237
2198
  const digest = logRecoverableError(request, x);
2238
2199
  emitErrorChunk(request, task.id, digest);
2239
- } finally {
2240
2200
  }
2241
2201
  }
2242
2202
 
@@ -2424,6 +2384,11 @@ function abort(request, reason) {
2424
2384
  }
2425
2385
  }
2426
2386
 
2387
+ function importServerContexts(contexts) {
2388
+
2389
+ return rootContextSnapshot;
2390
+ }
2391
+
2427
2392
  // This is the parsed shape of the wire format which is why it is
2428
2393
  // condensed to only the essentialy information
2429
2394
  const ID = 0;
@@ -3129,7 +3094,7 @@ function decodeFormState(actionResult, body, serverManifest) {
3129
3094
  }
3130
3095
 
3131
3096
  function renderToReadableStream(model, webpackMap, options) {
3132
- const request = createRequest(model, webpackMap, options ? options.onError : undefined, options ? options.identifierPrefix : undefined, options ? options.onPostpone : undefined);
3097
+ const request = createRequest(model, webpackMap, options ? options.onError : undefined, options ? options.context : undefined, options ? options.identifierPrefix : undefined, options ? options.onPostpone : undefined);
3133
3098
 
3134
3099
  if (options && options.signal) {
3135
3100
  const signal = options.signal;