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
@@ -10,8 +10,8 @@
10
10
 
11
11
  'use strict';
12
12
 
13
- var ReactDOM = require('react-dom');
14
13
  var React = require('react');
14
+ var ReactDOM = require('react-dom');
15
15
 
16
16
  // -----------------------------------------------------------------------------
17
17
  const enablePostpone = false;
@@ -19,7 +19,7 @@ const enablePostpone = false;
19
19
  function scheduleWork(callback) {
20
20
  setTimeout(callback, 0);
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.
@@ -689,7 +659,7 @@ typeof async_hooks === 'object' ? async_hooks.executionAsyncId : null;
689
659
  // The Symbol used to tag the ReactElement-like types.
690
660
  const REACT_ELEMENT_TYPE = Symbol.for('react.element');
691
661
  const REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
692
- const REACT_CONTEXT_TYPE = Symbol.for('react.context');
662
+ const REACT_SERVER_CONTEXT_TYPE = Symbol.for('react.server_context');
693
663
  const REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
694
664
  const REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
695
665
  const REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
@@ -713,6 +683,146 @@ function getIteratorFn(maybeIterable) {
713
683
  return null;
714
684
  }
715
685
 
686
+ // Forming a reverse tree.
687
+ // The structure of a context snapshot is an implementation of this file.
688
+ // Currently, it's implemented as tracking the current active node.
689
+
690
+
691
+ const rootContextSnapshot = null; // We assume that this runtime owns the "current" field on all ReactContext instances.
692
+ // This global (actually thread local) state represents what state all those "current",
693
+ // fields are currently in.
694
+
695
+ let currentActiveSnapshot = null;
696
+
697
+ function popNode(prev) {
698
+ {
699
+ prev.context._currentValue = prev.parentValue;
700
+ }
701
+ }
702
+
703
+ function pushNode(next) {
704
+ {
705
+ next.context._currentValue = next.value;
706
+ }
707
+ }
708
+
709
+ function popToNearestCommonAncestor(prev, next) {
710
+ if (prev === next) ; else {
711
+ popNode(prev);
712
+ const parentPrev = prev.parent;
713
+ const parentNext = next.parent;
714
+
715
+ if (parentPrev === null) {
716
+ if (parentNext !== null) {
717
+ throw new Error('The stacks must reach the root at the same time. This is a bug in React.');
718
+ }
719
+ } else {
720
+ if (parentNext === null) {
721
+ throw new Error('The stacks must reach the root at the same time. This is a bug in React.');
722
+ }
723
+
724
+ popToNearestCommonAncestor(parentPrev, parentNext); // On the way back, we push the new ones that weren't common.
725
+
726
+ pushNode(next);
727
+ }
728
+ }
729
+ }
730
+
731
+ function popAllPrevious(prev) {
732
+ popNode(prev);
733
+ const parentPrev = prev.parent;
734
+
735
+ if (parentPrev !== null) {
736
+ popAllPrevious(parentPrev);
737
+ }
738
+ }
739
+
740
+ function pushAllNext(next) {
741
+ const parentNext = next.parent;
742
+
743
+ if (parentNext !== null) {
744
+ pushAllNext(parentNext);
745
+ }
746
+
747
+ pushNode(next);
748
+ }
749
+
750
+ function popPreviousToCommonLevel(prev, next) {
751
+ popNode(prev);
752
+ const parentPrev = prev.parent;
753
+
754
+ if (parentPrev === null) {
755
+ throw new Error('The depth must equal at least at zero before reaching the root. This is a bug in React.');
756
+ }
757
+
758
+ if (parentPrev.depth === next.depth) {
759
+ // We found the same level. Now we just need to find a shared ancestor.
760
+ popToNearestCommonAncestor(parentPrev, next);
761
+ } else {
762
+ // We must still be deeper.
763
+ popPreviousToCommonLevel(parentPrev, next);
764
+ }
765
+ }
766
+
767
+ function popNextToCommonLevel(prev, next) {
768
+ const parentNext = next.parent;
769
+
770
+ if (parentNext === null) {
771
+ throw new Error('The depth must equal at least at zero before reaching the root. This is a bug in React.');
772
+ }
773
+
774
+ if (prev.depth === parentNext.depth) {
775
+ // We found the same level. Now we just need to find a shared ancestor.
776
+ popToNearestCommonAncestor(prev, parentNext);
777
+ } else {
778
+ // We must still be deeper.
779
+ popNextToCommonLevel(prev, parentNext);
780
+ }
781
+
782
+ pushNode(next);
783
+ } // Perform context switching to the new snapshot.
784
+ // To make it cheap to read many contexts, while not suspending, we make the switch eagerly by
785
+ // updating all the context's current values. That way reads, always just read the current value.
786
+ // At the cost of updating contexts even if they're never read by this subtree.
787
+
788
+
789
+ function switchContext(newSnapshot) {
790
+ // The basic algorithm we need to do is to pop back any contexts that are no longer on the stack.
791
+ // We also need to update any new contexts that are now on the stack with the deepest value.
792
+ // The easiest way to update new contexts is to just reapply them in reverse order from the
793
+ // perspective of the backpointers. To avoid allocating a lot when switching, we use the stack
794
+ // for that. Therefore this algorithm is recursive.
795
+ // 1) First we pop which ever snapshot tree was deepest. Popping old contexts as we go.
796
+ // 2) Then we find the nearest common ancestor from there. Popping old contexts as we go.
797
+ // 3) Then we reapply new contexts on the way back up the stack.
798
+ const prev = currentActiveSnapshot;
799
+ const next = newSnapshot;
800
+
801
+ if (prev !== next) {
802
+ if (prev === null) {
803
+ // $FlowFixMe[incompatible-call]: This has to be non-null since it's not equal to prev.
804
+ pushAllNext(next);
805
+ } else if (next === null) {
806
+ popAllPrevious(prev);
807
+ } else if (prev.depth === next.depth) {
808
+ popToNearestCommonAncestor(prev, next);
809
+ } else if (prev.depth > next.depth) {
810
+ popPreviousToCommonLevel(prev, next);
811
+ } else {
812
+ popNextToCommonLevel(prev, next);
813
+ }
814
+
815
+ currentActiveSnapshot = next;
816
+ }
817
+ }
818
+ function getActiveContext() {
819
+ return currentActiveSnapshot;
820
+ }
821
+ function readContext$1(context) {
822
+ const value = context._currentValue ;
823
+ return value;
824
+ }
825
+
716
826
  // Corresponds to ReactFiberWakeable and ReactFizzWakeable modules. Generally,
717
827
  // changes to one module should be reflected in the others.
718
828
  // TODO: Rename this module and the corresponding Fiber one to "Thenable"
@@ -841,13 +951,16 @@ function prepareToUseHooksForComponent(prevThenableState) {
841
951
  thenableState = prevThenableState;
842
952
  }
843
953
  function getThenableStateAfterSuspending() {
844
- // If you use() to Suspend this should always exist but if you throw a Promise instead,
845
- // which is not really supported anymore, it will be empty. We use the empty set as a
846
- // marker to know if this was a replay of the same component or first attempt.
847
- const state = thenableState || createThenableState();
954
+ const state = thenableState;
848
955
  thenableState = null;
849
956
  return state;
850
957
  }
958
+
959
+ function readContext(context) {
960
+
961
+ return readContext$1(context);
962
+ }
963
+
851
964
  const HooksDispatcher = {
852
965
  useMemo(nextCreate) {
853
966
  return nextCreate();
@@ -861,8 +974,8 @@ const HooksDispatcher = {
861
974
 
862
975
  useDeferredValue: unsupportedHook,
863
976
  useTransition: unsupportedHook,
864
- readContext: unsupportedContext,
865
- useContext: unsupportedContext,
977
+ readContext,
978
+ useContext: readContext,
866
979
  useReducer: unsupportedHook,
867
980
  useRef: unsupportedHook,
868
981
  useState: unsupportedHook,
@@ -898,10 +1011,6 @@ function unsupportedRefresh() {
898
1011
  throw new Error('Refreshing the cache is not supported in Server Components.');
899
1012
  }
900
1013
 
901
- function unsupportedContext() {
902
- throw new Error('Cannot read a Client Context from a Server Component.');
903
- }
904
-
905
1014
  function useId() {
906
1015
  if (currentRequest$1 === null) {
907
1016
  throw new Error('useId can only be used while React is rendering');
@@ -927,22 +1036,14 @@ function use(usable) {
927
1036
  }
928
1037
 
929
1038
  return trackUsedThenable(thenableState, thenable, index);
930
- } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {
931
- unsupportedContext();
1039
+ } else if (usable.$$typeof === REACT_SERVER_CONTEXT_TYPE) {
1040
+ const context = usable;
1041
+ return readContext(context);
932
1042
  }
933
1043
  }
934
1044
 
935
- if (isClientReference(usable)) {
936
- if (usable.value != null && usable.value.$$typeof === REACT_CONTEXT_TYPE) {
937
- // Show a more specific message since it's a common mistake.
938
- throw new Error('Cannot read a Client Context from a Server Component.');
939
- } else {
940
- throw new Error('Cannot use() an already resolved Client Reference.');
941
- }
942
- } else {
943
- throw new Error( // eslint-disable-next-line react-internal/safe-string-coercion
944
- 'An unsupported type was passed to use(): ' + String(usable));
945
- }
1045
+
1046
+ throw new Error('An unsupported type was passed to use(): ' + String(usable));
946
1047
  }
947
1048
 
948
1049
  function createSignal() {
@@ -1021,10 +1122,6 @@ function describeValueForErrorMessage(value) {
1021
1122
  return '[...]';
1022
1123
  }
1023
1124
 
1024
- if (value !== null && value.$$typeof === CLIENT_REFERENCE_TAG) {
1025
- return describeClientReference();
1026
- }
1027
-
1028
1125
  const name = objectName(value);
1029
1126
 
1030
1127
  if (name === 'Object') {
@@ -1035,14 +1132,7 @@ function describeValueForErrorMessage(value) {
1035
1132
  }
1036
1133
 
1037
1134
  case 'function':
1038
- {
1039
- if (value.$$typeof === CLIENT_REFERENCE_TAG) {
1040
- return describeClientReference();
1041
- }
1042
-
1043
- const name = value.displayName || value.name;
1044
- return name ? 'function ' + name : 'function';
1045
- }
1135
+ return 'function';
1046
1136
 
1047
1137
  default:
1048
1138
  // eslint-disable-next-line react-internal/safe-string-coercion
@@ -1088,12 +1178,6 @@ function describeElementType(type) {
1088
1178
  return '';
1089
1179
  }
1090
1180
 
1091
- const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
1092
-
1093
- function describeClientReference(ref) {
1094
- return 'client';
1095
- }
1096
-
1097
1181
  function describeObjectForErrorMessage(objectOrArray, expandedName) {
1098
1182
  const objKind = objectName(objectOrArray);
1099
1183
 
@@ -1141,8 +1225,6 @@ function describeObjectForErrorMessage(objectOrArray, expandedName) {
1141
1225
  } else {
1142
1226
  if (objectOrArray.$$typeof === REACT_ELEMENT_TYPE) {
1143
1227
  str = '<' + describeElementType(objectOrArray.type) + '/>';
1144
- } else if (objectOrArray.$$typeof === CLIENT_REFERENCE_TAG) {
1145
- return describeClientReference();
1146
1228
  } else {
1147
1229
  // Print Object
1148
1230
  str = '{';
@@ -1222,11 +1304,12 @@ function defaultPostponeHandler(reason) {// Noop
1222
1304
  const OPEN = 0;
1223
1305
  const CLOSING = 1;
1224
1306
  const CLOSED = 2;
1225
- function createRequest(model, bundlerConfig, onError, identifierPrefix, onPostpone, environmentName) {
1307
+ function createRequest(model, bundlerConfig, onError, context, identifierPrefix, onPostpone) {
1226
1308
  if (ReactCurrentCache.current !== null && ReactCurrentCache.current !== DefaultCacheDispatcher) {
1227
1309
  throw new Error('Currently React only supports one RSC renderer at a time.');
1228
1310
  }
1229
1311
 
1312
+ prepareHostDispatcher();
1230
1313
  ReactCurrentCache.current = DefaultCacheDispatcher;
1231
1314
  const abortSet = new Set();
1232
1315
  const pingedTasks = [];
@@ -1252,15 +1335,21 @@ function createRequest(model, bundlerConfig, onError, identifierPrefix, onPostpo
1252
1335
  writtenSymbols: new Map(),
1253
1336
  writtenClientReferences: new Map(),
1254
1337
  writtenServerReferences: new Map(),
1338
+ writtenProviders: new Map(),
1255
1339
  writtenObjects: new WeakMap(),
1256
1340
  identifierPrefix: identifierPrefix || '',
1257
1341
  identifierCount: 1,
1258
1342
  taintCleanupQueue: cleanupQueue,
1259
1343
  onError: onError === undefined ? defaultErrorHandler : onError,
1260
- onPostpone: onPostpone === undefined ? defaultPostponeHandler : onPostpone
1344
+ onPostpone: onPostpone === undefined ? defaultPostponeHandler : onPostpone,
1345
+ // $FlowFixMe[missing-this-annot]
1346
+ toJSON: function (key, value) {
1347
+ return resolveModelToJSON(request, this, key, value);
1348
+ }
1261
1349
  };
1262
-
1263
- const rootTask = createTask(request, model, null, false, abortSet);
1350
+ request.pendingChunks++;
1351
+ const rootContext = createRootContext();
1352
+ const rootTask = createTask(request, model, rootContext, abortSet);
1264
1353
  pingedTasks.push(rootTask);
1265
1354
  return request;
1266
1355
  }
@@ -1276,9 +1365,13 @@ function resolveRequest() {
1276
1365
  return null;
1277
1366
  }
1278
1367
 
1279
- function serializeThenable(request, task, thenable) {
1280
- const newTask = createTask(request, null, task.keyPath, // the server component sequence continues through Promise-as-a-child.
1281
- task.implicitSlot, request.abortableTasks);
1368
+ function createRootContext(reqContext) {
1369
+ return importServerContexts();
1370
+ }
1371
+
1372
+ function serializeThenable(request, thenable) {
1373
+ request.pendingChunks++;
1374
+ const newTask = createTask(request, null, getActiveContext(), request.abortableTasks);
1282
1375
 
1283
1376
  switch (thenable.status) {
1284
1377
  case 'fulfilled':
@@ -1412,117 +1505,61 @@ function createLazyWrapperAroundWakeable(wakeable) {
1412
1505
  _payload: thenable,
1413
1506
  _init: readThenable
1414
1507
  };
1415
-
1416
1508
  return lazyType;
1417
1509
  }
1418
1510
 
1419
- function renderFunctionComponent(request, task, key, Component, props) {
1420
- // Reset the task's thenable state before continuing, so that if a later
1421
- // component suspends we can reuse the same task object. If the same
1422
- // component suspends again, the thenable state will be restored.
1423
- const prevThenableState = task.thenableState;
1424
- task.thenableState = null;
1425
-
1426
- prepareToUseHooksForComponent(prevThenableState); // The secondArg is always undefined in Server Components since refs error early.
1427
-
1428
- const secondArg = undefined;
1429
- let result = Component(props, secondArg);
1430
-
1431
- if (typeof result === 'object' && result !== null && typeof result.then === 'function') {
1432
- // When the return value is in children position we can resolve it immediately,
1433
- // to its value without a wrapper if it's synchronously available.
1434
- const thenable = result;
1435
-
1436
- if (thenable.status === 'fulfilled') {
1437
- return thenable.value;
1438
- } // TODO: Once we accept Promises as children on the client, we can just return
1439
- // the thenable here.
1440
-
1441
-
1442
- result = createLazyWrapperAroundWakeable(result);
1443
- } // Track this element's key on the Server Component on the keyPath context..
1444
-
1445
-
1446
- const prevKeyPath = task.keyPath;
1447
- const prevImplicitSlot = task.implicitSlot;
1448
-
1449
- if (key !== null) {
1450
- // Append the key to the path. Technically a null key should really add the child
1451
- // index. We don't do that to hold the payload small and implementation simple.
1452
- task.keyPath = prevKeyPath === null ? key : prevKeyPath + ',' + key;
1453
- } else if (prevKeyPath === null) {
1454
- // This sequence of Server Components has no keys. This means that it was rendered
1455
- // in a slot that needs to assign an implicit key. Even if children below have
1456
- // explicit keys, they should not be used for the outer most key since it might
1457
- // collide with other slots in that set.
1458
- task.implicitSlot = true;
1459
- }
1460
-
1461
- const json = renderModelDestructive(request, task, emptyRoot, '', result);
1462
- task.keyPath = prevKeyPath;
1463
- task.implicitSlot = prevImplicitSlot;
1464
- return json;
1465
- }
1466
-
1467
- function renderFragment(request, task, children) {
1468
-
1469
- {
1470
- return children;
1471
- }
1472
- }
1473
-
1474
- function renderClientElement(task, type, key, props) {
1475
- {
1476
- return [REACT_ELEMENT_TYPE, type, key, props];
1477
- } // We prepend the terminal client element that actually gets serialized with
1478
- } // The chunk ID we're currently rendering that we can assign debug data to.
1479
-
1480
-
1481
- let debugID = null;
1482
-
1483
- function renderElement(request, task, type, key, ref, props) {
1511
+ function attemptResolveElement(request, type, key, ref, props, prevThenableState) {
1484
1512
  if (ref !== null && ref !== undefined) {
1485
1513
  // When the ref moves to the regular props object this will implicitly
1486
1514
  // throw for functions. We could probably relax it to a DEV warning for other
1487
1515
  // cases.
1488
- // TODO: `ref` is now just a prop when `enableRefAsProp` is on. Should we
1489
- // do what the above comment says?
1490
1516
  throw new Error('Refs cannot be used in Server Components, nor passed to Client Components.');
1491
1517
  }
1492
1518
 
1493
1519
  if (typeof type === 'function') {
1494
1520
  if (isClientReference(type)) {
1495
1521
  // This is a reference to a Client Component.
1496
- return renderClientElement(task, type, key, props);
1497
- } // This is a Server Component.
1522
+ return [REACT_ELEMENT_TYPE, type, key, props];
1523
+ } // This is a server-side component.
1498
1524
 
1499
1525
 
1500
- return renderFunctionComponent(request, task, key, type, props);
1526
+ prepareToUseHooksForComponent(prevThenableState);
1527
+ const result = type(props);
1528
+
1529
+ if (typeof result === 'object' && result !== null && typeof result.then === 'function') {
1530
+ // When the return value is in children position we can resolve it immediately,
1531
+ // to its value without a wrapper if it's synchronously available.
1532
+ const thenable = result;
1533
+
1534
+ if (thenable.status === 'fulfilled') {
1535
+ return thenable.value;
1536
+ } // TODO: Once we accept Promises as children on the client, we can just return
1537
+ // the thenable here.
1538
+
1539
+
1540
+ return createLazyWrapperAroundWakeable(result);
1541
+ }
1542
+
1543
+ return result;
1501
1544
  } else if (typeof type === 'string') {
1502
1545
  // This is a host element. E.g. HTML.
1503
- return renderClientElement(task, type, key, props);
1546
+ return [REACT_ELEMENT_TYPE, type, key, props];
1504
1547
  } else if (typeof type === 'symbol') {
1505
- if (type === REACT_FRAGMENT_TYPE && key === null) {
1548
+ if (type === REACT_FRAGMENT_TYPE) {
1506
1549
  // For key-less fragments, we add a small optimization to avoid serializing
1507
1550
  // it as a wrapper.
1508
- const prevImplicitSlot = task.implicitSlot;
1509
-
1510
- if (task.keyPath === null) {
1511
- task.implicitSlot = true;
1512
- }
1513
-
1514
- const json = renderModelDestructive(request, task, emptyRoot, '', props.children);
1515
- task.implicitSlot = prevImplicitSlot;
1516
- return json;
1551
+ // TODO: If a key is specified, we should propagate its key to any children.
1552
+ // Same as if a Server Component has a key.
1553
+ return props.children;
1517
1554
  } // This might be a built-in React component. We'll let the client decide.
1518
1555
  // Any built-in works as long as its props are serializable.
1519
1556
 
1520
1557
 
1521
- return renderClientElement(task, type, key, props);
1558
+ return [REACT_ELEMENT_TYPE, type, key, props];
1522
1559
  } else if (type != null && typeof type === 'object') {
1523
1560
  if (isClientReference(type)) {
1524
1561
  // This is a reference to a Client Component.
1525
- return renderClientElement(task, type, key, props);
1562
+ return [REACT_ELEMENT_TYPE, type, key, props];
1526
1563
  }
1527
1564
 
1528
1565
  switch (type.$$typeof) {
@@ -1531,17 +1568,19 @@ function renderElement(request, task, type, key, ref, props) {
1531
1568
  const payload = type._payload;
1532
1569
  const init = type._init;
1533
1570
  const wrappedType = init(payload);
1534
- return renderElement(request, task, wrappedType, key, ref, props);
1571
+ return attemptResolveElement(request, wrappedType, key, ref, props, prevThenableState);
1535
1572
  }
1536
1573
 
1537
1574
  case REACT_FORWARD_REF_TYPE:
1538
1575
  {
1539
- return renderFunctionComponent(request, task, key, type.render, props);
1576
+ const render = type.render;
1577
+ prepareToUseHooksForComponent(prevThenableState);
1578
+ return render(props, undefined);
1540
1579
  }
1541
1580
 
1542
1581
  case REACT_MEMO_TYPE:
1543
1582
  {
1544
- return renderElement(request, task, type.type, key, ref, props);
1583
+ return attemptResolveElement(request, type.type, key, ref, props, prevThenableState);
1545
1584
  }
1546
1585
  }
1547
1586
  }
@@ -1559,30 +1598,14 @@ function pingTask(request, task) {
1559
1598
  }
1560
1599
  }
1561
1600
 
1562
- function createTask(request, model, keyPath, implicitSlot, abortSet) {
1563
- request.pendingChunks++;
1601
+ function createTask(request, model, context, abortSet) {
1564
1602
  const id = request.nextChunkId++;
1565
-
1566
- if (typeof model === 'object' && model !== null) {
1567
- // If we're about to write this into a new task we can assign it an ID early so that
1568
- // any other references can refer to the value we're about to write.
1569
- {
1570
- request.writtenObjects.set(model, id);
1571
- }
1572
- }
1573
-
1574
1603
  const task = {
1575
1604
  id,
1576
1605
  status: PENDING$1,
1577
1606
  model,
1578
- keyPath,
1579
- implicitSlot,
1607
+ context,
1580
1608
  ping: () => pingTask(request, task),
1581
- toJSON: function (parentPropertyName, value) {
1582
- const parent = this; // Make sure that `parent[parentPropertyName]` wasn't JSONified before `value` was passed to us
1583
-
1584
- return renderModel(request, task, parent, parentPropertyName, value);
1585
- },
1586
1609
  thenableState: null
1587
1610
  };
1588
1611
  abortSet.add(task);
@@ -1651,13 +1674,13 @@ function encodeReferenceChunk(request, id, reference) {
1651
1674
  return stringToChunk(row);
1652
1675
  }
1653
1676
 
1654
- function serializeClientReference(request, parent, parentPropertyName, clientReference) {
1677
+ function serializeClientReference(request, parent, key, clientReference) {
1655
1678
  const clientReferenceKey = getClientReferenceKey(clientReference);
1656
1679
  const writtenClientReferences = request.writtenClientReferences;
1657
1680
  const existingId = writtenClientReferences.get(clientReferenceKey);
1658
1681
 
1659
1682
  if (existingId !== undefined) {
1660
- if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {
1683
+ if (parent[0] === REACT_ELEMENT_TYPE && key === '1') {
1661
1684
  // If we're encoding the "type" of an element, we can refer
1662
1685
  // to that by a lazy reference instead of directly since React
1663
1686
  // knows how to deal with lazy values. This lets us suspend
@@ -1676,7 +1699,7 @@ function serializeClientReference(request, parent, parentPropertyName, clientRef
1676
1699
  emitImportChunk(request, importId, clientReferenceMetadata);
1677
1700
  writtenClientReferences.set(clientReferenceKey, importId);
1678
1701
 
1679
- if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {
1702
+ if (parent[0] === REACT_ELEMENT_TYPE && key === '1') {
1680
1703
  // If we're encoding the "type" of an element, we can refer
1681
1704
  // to that by a lazy reference instead of directly since React
1682
1705
  // knows how to deal with lazy values. This lets us suspend
@@ -1696,14 +1719,13 @@ function serializeClientReference(request, parent, parentPropertyName, clientRef
1696
1719
  }
1697
1720
 
1698
1721
  function outlineModel(request, value) {
1699
- const newTask = createTask(request, value, null, // The way we use outlining is for reusing an object.
1700
- false, // It makes no sense for that use case to be contextual.
1701
- request.abortableTasks);
1722
+ request.pendingChunks++;
1723
+ const newTask = createTask(request, value, getActiveContext(), request.abortableTasks);
1702
1724
  retryTask(request, newTask);
1703
1725
  return newTask.id;
1704
1726
  }
1705
1727
 
1706
- function serializeServerReference(request, serverReference) {
1728
+ function serializeServerReference(request, parent, key, serverReference) {
1707
1729
  const writtenServerReferences = request.writtenServerReferences;
1708
1730
  const existingId = writtenServerReferences.get(serverReference);
1709
1731
 
@@ -1783,77 +1805,91 @@ function escapeStringValue(value) {
1783
1805
  return value;
1784
1806
  }
1785
1807
  }
1786
-
1787
1808
  let modelRoot = false;
1788
1809
 
1789
- function renderModel(request, task, parent, key, value) {
1790
- const prevKeyPath = task.keyPath;
1791
- const prevImplicitSlot = task.implicitSlot;
1810
+ function resolveModelToJSON(request, parent, key, value) {
1792
1811
 
1793
- try {
1794
- return renderModelDestructive(request, task, parent, key, value);
1795
- } catch (thrownValue) {
1796
- const x = thrownValue === SuspenseException ? // This is a special type of exception used for Suspense. For historical
1797
- // reasons, the rest of the Suspense implementation expects the thrown
1798
- // value to be a thenable, because before `use` existed that was the
1799
- // (unstable) API for suspending. This implementation detail can change
1800
- // later, once we deprecate the old API in favor of `use`.
1801
- getSuspendedThenable() : thrownValue; // If the suspended/errored value was an element or lazy it can be reduced
1802
- // to a lazy reference, so that it doesn't error the parent.
1803
1812
 
1804
- const model = task.model;
1805
- const wasReactNode = typeof model === 'object' && model !== null && (model.$$typeof === REACT_ELEMENT_TYPE || model.$$typeof === REACT_LAZY_TYPE);
1813
+ switch (value) {
1814
+ case REACT_ELEMENT_TYPE:
1815
+ return '$';
1816
+ }
1806
1817
 
1807
- if (typeof x === 'object' && x !== null) {
1808
- // $FlowFixMe[method-unbinding]
1809
- if (typeof x.then === 'function') {
1810
- // Something suspended, we'll need to create a new task and resolve it later.
1811
- const newTask = createTask(request, task.model, task.keyPath, task.implicitSlot, request.abortableTasks);
1812
- const ping = newTask.ping;
1813
- x.then(ping, ping);
1814
- newTask.thenableState = getThenableStateAfterSuspending(); // Restore the context. We assume that this will be restored by the inner
1815
- // functions in case nothing throws so we don't use "finally" here.
1816
1818
 
1817
- task.keyPath = prevKeyPath;
1818
- task.implicitSlot = prevImplicitSlot;
1819
+ while (typeof value === 'object' && value !== null && (value.$$typeof === REACT_ELEMENT_TYPE || value.$$typeof === REACT_LAZY_TYPE)) {
1819
1820
 
1820
- if (wasReactNode) {
1821
- return serializeLazyID(newTask.id);
1822
- }
1821
+ try {
1822
+ switch (value.$$typeof) {
1823
+ case REACT_ELEMENT_TYPE:
1824
+ {
1825
+ const writtenObjects = request.writtenObjects;
1826
+ const existingId = writtenObjects.get(value);
1827
+
1828
+ if (existingId !== undefined) {
1829
+ if (existingId === -1) {
1830
+ // Seen but not yet outlined.
1831
+ const newId = outlineModel(request, value);
1832
+ return serializeByValueID(newId);
1833
+ } else if (modelRoot === value) {
1834
+ // This is the ID we're currently emitting so we need to write it
1835
+ // once but if we discover it again, we refer to it by id.
1836
+ modelRoot = null;
1837
+ } else {
1838
+ // We've already emitted this as an outlined object, so we can
1839
+ // just refer to that by its existing ID.
1840
+ return serializeByValueID(existingId);
1841
+ }
1842
+ } else {
1843
+ // This is the first time we've seen this object. We may never see it again
1844
+ // so we'll inline it. Mark it as seen. If we see it again, we'll outline.
1845
+ writtenObjects.set(value, -1);
1846
+ } // TODO: Concatenate keys of parents onto children.
1823
1847
 
1824
- return serializeByValueID(newTask.id);
1825
- }
1826
- } // Restore the context. We assume that this will be restored by the inner
1827
- // functions in case nothing throws so we don't use "finally" here.
1828
1848
 
1849
+ const element = value; // Attempt to render the Server Component.
1829
1850
 
1830
- task.keyPath = prevKeyPath;
1831
- task.implicitSlot = prevImplicitSlot;
1851
+ value = attemptResolveElement(request, element.type, element.key, element.ref, element.props, null);
1852
+ break;
1853
+ }
1832
1854
 
1833
- if (wasReactNode) {
1834
- // Something errored. We'll still send everything we have up until this point.
1855
+ case REACT_LAZY_TYPE:
1856
+ {
1857
+ const payload = value._payload;
1858
+ const init = value._init;
1859
+ value = init(payload);
1860
+ break;
1861
+ }
1862
+ }
1863
+ } catch (thrownValue) {
1864
+ const x = thrownValue === SuspenseException ? // This is a special type of exception used for Suspense. For historical
1865
+ // reasons, the rest of the Suspense implementation expects the thrown
1866
+ // value to be a thenable, because before `use` existed that was the
1867
+ // (unstable) API for suspending. This implementation detail can change
1868
+ // later, once we deprecate the old API in favor of `use`.
1869
+ getSuspendedThenable() : thrownValue;
1870
+
1871
+ if (typeof x === 'object' && x !== null) {
1872
+ // $FlowFixMe[method-unbinding]
1873
+ if (typeof x.then === 'function') {
1874
+ // Something suspended, we'll need to create a new task and resolve it later.
1875
+ request.pendingChunks++;
1876
+ const newTask = createTask(request, value, getActiveContext(), request.abortableTasks);
1877
+ const ping = newTask.ping;
1878
+ x.then(ping, ping);
1879
+ newTask.thenableState = getThenableStateAfterSuspending();
1880
+ return serializeLazyID(newTask.id);
1881
+ }
1882
+ } // Something errored. We'll still send everything we have up until this point.
1835
1883
  // We'll replace this element with a lazy reference that throws on the client
1836
1884
  // once it gets rendered.
1885
+
1886
+
1837
1887
  request.pendingChunks++;
1838
1888
  const errorId = request.nextChunkId++;
1839
1889
  const digest = logRecoverableError(request, x);
1840
1890
  emitErrorChunk(request, errorId, digest);
1841
1891
  return serializeLazyID(errorId);
1842
- } // Something errored but it was not in a React Node. There's no need to serialize
1843
- // it by value because it'll just error the whole parent row anyway so we can
1844
- // just stop any siblings and error the whole parent row.
1845
-
1846
-
1847
- throw x;
1848
- }
1849
- }
1850
-
1851
- function renderModelDestructive(request, task, parent, parentPropertyName, value) {
1852
- // Set the currently rendering model
1853
- task.model = value; // Special Symbol, that's very common.
1854
-
1855
- if (value === REACT_ELEMENT_TYPE) {
1856
- return '$';
1892
+ }
1857
1893
  }
1858
1894
 
1859
1895
  if (value === null) {
@@ -1861,70 +1897,9 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1861
1897
  }
1862
1898
 
1863
1899
  if (typeof value === 'object') {
1864
- switch (value.$$typeof) {
1865
- case REACT_ELEMENT_TYPE:
1866
- {
1867
- const writtenObjects = request.writtenObjects;
1868
- const existingId = writtenObjects.get(value);
1869
-
1870
- if (existingId !== undefined) {
1871
- if (modelRoot === value) {
1872
- // This is the ID we're currently emitting so we need to write it
1873
- // once but if we discover it again, we refer to it by id.
1874
- modelRoot = null;
1875
- } else if (existingId === -1) {
1876
- // Seen but not yet outlined.
1877
- // TODO: If we throw here we can treat this as suspending which causes an outline
1878
- // but that is able to reuse the same task if we're already in one but then that
1879
- // will be a lazy future value rather than guaranteed to exist but maybe that's good.
1880
- const newId = outlineModel(request, value);
1881
- return serializeByValueID(newId);
1882
- } else {
1883
- // We've already emitted this as an outlined object, so we can refer to that by its
1884
- // existing ID. TODO: We should use a lazy reference since, unlike plain objects,
1885
- // elements might suspend so it might not have emitted yet even if we have the ID for
1886
- // it. However, this creates an extra wrapper when it's not needed. We should really
1887
- // detect whether this already was emitted and synchronously available. In that
1888
- // case we can refer to it synchronously and only make it lazy otherwise.
1889
- // We currently don't have a data structure that lets us see that though.
1890
- return serializeByValueID(existingId);
1891
- }
1892
- } else {
1893
- // This is the first time we've seen this object. We may never see it again
1894
- // so we'll inline it. Mark it as seen. If we see it again, we'll outline.
1895
- writtenObjects.set(value, -1);
1896
- }
1897
-
1898
- const element = value;
1899
-
1900
- const props = element.props;
1901
- let ref;
1902
-
1903
- {
1904
- ref = element.ref;
1905
- } // Attempt to render the Server Component.
1906
-
1907
-
1908
- return renderElement(request, task, element.type, // $FlowFixMe[incompatible-call] the key of an element is null | string
1909
- element.key, ref, props);
1910
- }
1911
-
1912
- case REACT_LAZY_TYPE:
1913
- {
1914
- // Reset the task's thenable state before continuing. If there was one, it was
1915
- // from suspending the lazy before.
1916
- task.thenableState = null;
1917
- const lazy = value;
1918
- const payload = lazy._payload;
1919
- const init = lazy._init;
1920
- const resolvedModel = init(payload);
1921
-
1922
- return renderModelDestructive(request, task, emptyRoot, '', resolvedModel);
1923
- }
1924
- }
1925
1900
 
1926
1901
  if (isClientReference(value)) {
1927
- return serializeClientReference(request, parent, parentPropertyName, value);
1902
+ return serializeClientReference(request, parent, key, value);
1928
1903
  }
1929
1904
 
1930
1905
  const writtenObjects = request.writtenObjects;
@@ -1944,20 +1919,20 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1944
1919
  // or a Promise type. Either of which can be represented by a Promise.
1945
1920
 
1946
1921
 
1947
- const promiseId = serializeThenable(request, task, value);
1922
+ const promiseId = serializeThenable(request, value);
1948
1923
  writtenObjects.set(value, promiseId);
1949
1924
  return serializePromiseID(promiseId);
1950
1925
  }
1951
1926
 
1952
1927
  if (existingId !== undefined) {
1953
- if (modelRoot === value) {
1954
- // This is the ID we're currently emitting so we need to write it
1955
- // once but if we discover it again, we refer to it by id.
1956
- modelRoot = null;
1957
- } else if (existingId === -1) {
1928
+ if (existingId === -1) {
1958
1929
  // Seen but not yet outlined.
1959
1930
  const newId = outlineModel(request, value);
1960
1931
  return serializeByValueID(newId);
1932
+ } else if (modelRoot === value) {
1933
+ // This is the ID we're currently emitting so we need to write it
1934
+ // once but if we discover it again, we refer to it by id.
1935
+ modelRoot = null;
1961
1936
  } else {
1962
1937
  // We've already emitted this as an outlined object, so we can
1963
1938
  // just refer to that by its existing ID.
@@ -1970,7 +1945,8 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1970
1945
  }
1971
1946
 
1972
1947
  if (isArray(value)) {
1973
- return renderFragment(request, task, value);
1948
+ // $FlowFixMe[incompatible-return]
1949
+ return value;
1974
1950
  }
1975
1951
 
1976
1952
  if (value instanceof Map) {
@@ -1984,7 +1960,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1984
1960
  const iteratorFn = getIteratorFn(value);
1985
1961
 
1986
1962
  if (iteratorFn) {
1987
- return renderFragment(request, task, Array.from(value));
1963
+ return Array.from(value);
1988
1964
  } // Verify that this is a simple plain object.
1989
1965
 
1990
1966
 
@@ -2004,7 +1980,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2004
1980
  if (value[value.length - 1] === 'Z') {
2005
1981
  // Possibly a Date, whose toJSON automatically calls toISOString
2006
1982
  // $FlowFixMe[incompatible-use]
2007
- const originalValue = parent[parentPropertyName];
1983
+ const originalValue = parent[key];
2008
1984
 
2009
1985
  if (originalValue instanceof Date) {
2010
1986
  return serializeDateFromDateJSON(value);
@@ -2034,18 +2010,19 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2034
2010
  }
2035
2011
 
2036
2012
  if (typeof value === 'function') {
2013
+
2037
2014
  if (isClientReference(value)) {
2038
- return serializeClientReference(request, parent, parentPropertyName, value);
2015
+ return serializeClientReference(request, parent, key, value);
2039
2016
  }
2040
2017
 
2041
2018
  if (isServerReference(value)) {
2042
- return serializeServerReference(request, value);
2019
+ return serializeServerReference(request, parent, key, value);
2043
2020
  }
2044
2021
 
2045
- if (/^on[A-Z]/.test(parentPropertyName)) {
2046
- 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.');
2022
+ if (/^on[A-Z]/.test(key)) {
2023
+ 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.');
2047
2024
  } else {
2048
- 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));
2025
+ 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));
2049
2026
  }
2050
2027
  }
2051
2028
 
@@ -2062,7 +2039,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2062
2039
 
2063
2040
  if (Symbol.for(name) !== value) {
2064
2041
  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
2065
- value.description + ") cannot be found among global symbols.") + describeObjectForErrorMessage(parent, parentPropertyName));
2042
+ value.description + ") cannot be found among global symbols.") + describeObjectForErrorMessage(parent, key));
2066
2043
  }
2067
2044
 
2068
2045
  request.pendingChunks++;
@@ -2077,44 +2054,17 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2077
2054
  return serializeBigInt(value);
2078
2055
  }
2079
2056
 
2080
- throw new Error("Type " + typeof value + " is not supported in Client Component props." + describeObjectForErrorMessage(parent, parentPropertyName));
2057
+ throw new Error("Type " + typeof value + " is not supported in Client Component props." + describeObjectForErrorMessage(parent, key));
2081
2058
  }
2082
2059
 
2083
2060
  function logPostpone(request, reason) {
2084
- const prevRequest = currentRequest;
2085
- currentRequest = null;
2086
-
2087
- try {
2088
- const onPostpone = request.onPostpone;
2089
-
2090
- if (supportsRequestStorage) {
2091
- // Exit the request context while running callbacks.
2092
- requestStorage.run(undefined, onPostpone, reason);
2093
- } else {
2094
- onPostpone(reason);
2095
- }
2096
- } finally {
2097
- currentRequest = prevRequest;
2098
- }
2061
+ const onPostpone = request.onPostpone;
2062
+ onPostpone(reason);
2099
2063
  }
2100
2064
 
2101
2065
  function logRecoverableError(request, error) {
2102
- const prevRequest = currentRequest;
2103
- currentRequest = null;
2104
- let errorDigest;
2105
-
2106
- try {
2107
- const onError = request.onError;
2108
-
2109
- if (supportsRequestStorage) {
2110
- // Exit the request context while running callbacks.
2111
- errorDigest = requestStorage.run(undefined, onError, error);
2112
- } else {
2113
- errorDigest = onError(error);
2114
- }
2115
- } finally {
2116
- currentRequest = prevRequest;
2117
- }
2066
+ const onError = request.onError;
2067
+ const errorDigest = onError(error);
2118
2068
 
2119
2069
  if (errorDigest != null && typeof errorDigest !== 'string') {
2120
2070
  // eslint-disable-next-line react-internal/prod-error-codes
@@ -2184,54 +2134,62 @@ function emitSymbolChunk(request, id, name) {
2184
2134
  request.completedImportChunks.push(processedChunk);
2185
2135
  }
2186
2136
 
2187
- function emitModelChunk(request, id, json) {
2137
+ function emitModelChunk(request, id, model) {
2138
+ // Track the root so we know that we have to emit this object even though it
2139
+ // already has an ID. This is needed because we might see this object twice
2140
+ // in the same toJSON if it is cyclic.
2141
+ modelRoot = model; // $FlowFixMe[incompatible-type] stringify can return null
2142
+
2143
+ const json = stringify(model, request.toJSON);
2188
2144
  const row = id.toString(16) + ':' + json + '\n';
2189
2145
  const processedChunk = stringToChunk(row);
2190
2146
  request.completedRegularChunks.push(processedChunk);
2191
2147
  }
2192
2148
 
2193
- const emptyRoot = {};
2194
-
2195
2149
  function retryTask(request, task) {
2196
2150
  if (task.status !== PENDING$1) {
2197
2151
  // We completed this by other means before we had a chance to retry it.
2198
2152
  return;
2199
2153
  }
2200
2154
 
2155
+ switchContext(task.context);
2156
+
2201
2157
  try {
2202
- // Track the root so we know that we have to emit this object even though it
2203
- // already has an ID. This is needed because we might see this object twice
2204
- // in the same toJSON if it is cyclic.
2205
- modelRoot = task.model;
2158
+ let value = task.model;
2206
2159
 
2207
- if (false) ; // We call the destructive form that mutates this task. That way if something
2208
- // suspends again, we can reuse the same task instead of spawning a new one.
2160
+ if (typeof value === 'object' && value !== null && value.$$typeof === REACT_ELEMENT_TYPE) {
2161
+ request.writtenObjects.set(value, task.id); // TODO: Concatenate keys of parents onto children.
2209
2162
 
2163
+ const element = value; // When retrying a component, reuse the thenableState from the
2164
+ // previous attempt.
2210
2165
 
2211
- const resolvedModel = renderModelDestructive(request, task, emptyRoot, '', task.model);
2166
+ const prevThenableState = task.thenableState; // Attempt to render the Server Component.
2167
+ // Doing this here lets us reuse this same task if the next component
2168
+ // also suspends.
2212
2169
 
2213
- if (false) ; // Track the root again for the resolved object.
2170
+ task.model = value;
2171
+ value = attemptResolveElement(request, element.type, element.key, element.ref, element.props, prevThenableState); // Successfully finished this component. We're going to keep rendering
2172
+ // using the same task, but we reset its thenable state before continuing.
2214
2173
 
2174
+ task.thenableState = null; // Keep rendering and reuse the same task. This inner loop is separate
2175
+ // from the render above because we don't need to reset the thenable state
2176
+ // until the next time something suspends and retries.
2215
2177
 
2216
- modelRoot = resolvedModel; // The keyPath resets at any terminal child node.
2178
+ while (typeof value === 'object' && value !== null && value.$$typeof === REACT_ELEMENT_TYPE) {
2179
+ request.writtenObjects.set(value, task.id); // TODO: Concatenate keys of parents onto children.
2217
2180
 
2218
- task.keyPath = null;
2219
- task.implicitSlot = false;
2220
- let json;
2181
+ const nextElement = value;
2182
+ task.model = value;
2183
+ value = attemptResolveElement(request, nextElement.type, nextElement.key, nextElement.ref, nextElement.props, null);
2184
+ }
2185
+ } // Track that this object is outlined and has an id.
2221
2186
 
2222
- if (typeof resolvedModel === 'object' && resolvedModel !== null) {
2223
- // Object might contain unresolved values like additional elements.
2224
- // This is simulating what the JSON loop would do if this was part of it.
2225
- // $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do
2226
- json = stringify(resolvedModel, task.toJSON);
2227
- } else {
2228
- // If the value is a string, it means it's a terminal value and we already escaped it
2229
- // We don't need to escape it again so it's not passed the toJSON replacer.
2230
- // $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do
2231
- json = stringify(resolvedModel);
2187
+
2188
+ if (typeof value === 'object' && value !== null) {
2189
+ request.writtenObjects.set(value, task.id);
2232
2190
  }
2233
2191
 
2234
- emitModelChunk(request, task.id, json);
2192
+ emitModelChunk(request, task.id, value);
2235
2193
  request.abortableTasks.delete(task);
2236
2194
  task.status = COMPLETED;
2237
2195
  } catch (thrownValue) {
@@ -2257,7 +2215,6 @@ function retryTask(request, task) {
2257
2215
  task.status = ERRORED$1;
2258
2216
  const digest = logRecoverableError(request, x);
2259
2217
  emitErrorChunk(request, task.id, digest);
2260
- } finally {
2261
2218
  }
2262
2219
  }
2263
2220
 
@@ -2447,6 +2404,11 @@ function abort(request, reason) {
2447
2404
  }
2448
2405
  }
2449
2406
 
2407
+ function importServerContexts(contexts) {
2408
+
2409
+ return rootContextSnapshot;
2410
+ }
2411
+
2450
2412
  // This is the parsed shape of the wire format which is why it is
2451
2413
  // condensed to only the essentialy information
2452
2414
  const ID = 0;
@@ -3133,7 +3095,7 @@ function decodeFormState(actionResult, body, serverManifest) {
3133
3095
  }
3134
3096
 
3135
3097
  function renderToReadableStream(model, webpackMap, options) {
3136
- const request = createRequest(model, webpackMap, options ? options.onError : undefined, options ? options.identifierPrefix : undefined, options ? options.onPostpone : undefined);
3098
+ const request = createRequest(model, webpackMap, options ? options.onError : undefined, options ? options.context : undefined, options ? options.identifierPrefix : undefined, options ? options.onPostpone : undefined);
3137
3099
 
3138
3100
  if (options && options.signal) {
3139
3101
  const signal = options.signal;