react-server-dom-webpack 18.3.0-canary-14898b6a9-20240318 → 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 +91 -189
  2. package/cjs/react-server-dom-webpack-client.browser.production.js +60 -43
  3. package/cjs/react-server-dom-webpack-client.browser.production.min.js +24 -23
  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 +96 -241
  6. package/cjs/react-server-dom-webpack-client.edge.production.js +65 -84
  7. package/cjs/react-server-dom-webpack-client.edge.production.min.js +29 -29
  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 +96 -241
  10. package/cjs/react-server-dom-webpack-client.node.production.js +65 -84
  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 +96 -241
  14. package/cjs/react-server-dom-webpack-client.node.unbundled.production.js +65 -84
  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 +406 -550
  20. package/cjs/react-server-dom-webpack-server.browser.production.js +351 -373
  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 +406 -553
  24. package/cjs/react-server-dom-webpack-server.edge.production.js +350 -375
  25. package/cjs/react-server-dom-webpack-server.edge.production.min.js +69 -66
  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 +406 -550
  28. package/cjs/react-server-dom-webpack-server.node.production.js +350 -372
  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 +406 -550
  32. package/cjs/react-server-dom-webpack-server.node.unbundled.production.js +350 -372
  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 +3 -3
  36. package/umd/react-server-dom-webpack-client.browser.development.js +91 -189
  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 +406 -550
  39. package/umd/react-server-dom-webpack-server.browser.production.min.js +52 -52
@@ -109,10 +109,10 @@ function closeWithError(destination, error) {
109
109
  }
110
110
 
111
111
  // eslint-disable-next-line no-unused-vars
112
- const CLIENT_REFERENCE_TAG$1 = Symbol.for('react.client.reference');
112
+ const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
113
113
  const SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');
114
114
  function isClientReference(reference) {
115
- return reference.$$typeof === CLIENT_REFERENCE_TAG$1;
115
+ return reference.$$typeof === CLIENT_REFERENCE_TAG;
116
116
  }
117
117
  function isServerReference(reference) {
118
118
  return reference.$$typeof === SERVER_REFERENCE_TAG;
@@ -124,7 +124,7 @@ function registerClientReference(proxyImplementation, id, exportName) {
124
124
  function registerClientReferenceImpl(proxyImplementation, id, async) {
125
125
  return Object.defineProperties(proxyImplementation, {
126
126
  $$typeof: {
127
- value: CLIENT_REFERENCE_TAG$1
127
+ value: CLIENT_REFERENCE_TAG
128
128
  },
129
129
  $$id: {
130
130
  value: id
@@ -145,7 +145,6 @@ function bind() {
145
145
  const newFn = FunctionBind.apply(this, arguments);
146
146
 
147
147
  if (this.$$typeof === SERVER_REFERENCE_TAG) {
148
-
149
148
  const args = ArraySlice.call(arguments, 1);
150
149
  return Object.defineProperties(newFn, {
151
150
  $$typeof: {
@@ -172,16 +171,13 @@ function registerServerReference(reference, id, exportName) {
172
171
  value: SERVER_REFERENCE_TAG
173
172
  },
174
173
  $$id: {
175
- value: exportName === null ? id : id + '#' + exportName,
176
- configurable: true
174
+ value: exportName === null ? id : id + '#' + exportName
177
175
  },
178
176
  $$bound: {
179
- value: null,
180
- configurable: true
177
+ value: null
181
178
  },
182
179
  bind: {
183
- value: bind,
184
- configurable: true
180
+ value: bind
185
181
  }
186
182
  });
187
183
  }
@@ -220,10 +216,6 @@ const deepProxyHandlers = {
220
216
  // $FlowFixMe[prop-missing]
221
217
  return Object.prototype[Symbol.toPrimitive];
222
218
 
223
- case Symbol.toStringTag:
224
- // $FlowFixMe[prop-missing]
225
- return Object.prototype[Symbol.toStringTag];
226
-
227
219
  case 'Provider':
228
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.");
229
221
  } // eslint-disable-next-line react-internal/safe-string-coercion
@@ -265,10 +257,6 @@ function getReference(target, name) {
265
257
  // $FlowFixMe[prop-missing]
266
258
  return Object.prototype[Symbol.toPrimitive];
267
259
 
268
- case Symbol.toStringTag:
269
- // $FlowFixMe[prop-missing]
270
- return Object.prototype[Symbol.toStringTag];
271
-
272
260
  case '__esModule':
273
261
  // Something is conditionally checking which export to use. We'll pretend to be
274
262
  // an ESM compat module but then we'll check again on the client.
@@ -309,10 +297,6 @@ function getReference(target, name) {
309
297
 
310
298
  }
311
299
 
312
- if (typeof name === 'symbol') {
313
- throw new Error('Cannot read Symbol exports. Only named exports are supported on a client module ' + 'imported on the server.');
314
- }
315
-
316
300
  let cachedReference = target[name];
317
301
 
318
302
  if (!cachedReference) {
@@ -675,7 +659,7 @@ typeof async_hooks === 'object' ? async_hooks.executionAsyncId : null;
675
659
  // The Symbol used to tag the ReactElement-like types.
676
660
  const REACT_ELEMENT_TYPE = Symbol.for('react.element');
677
661
  const REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
678
- const REACT_CONTEXT_TYPE = Symbol.for('react.context');
662
+ const REACT_SERVER_CONTEXT_TYPE = Symbol.for('react.server_context');
679
663
  const REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
680
664
  const REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
681
665
  const REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
@@ -699,6 +683,146 @@ function getIteratorFn(maybeIterable) {
699
683
  return null;
700
684
  }
701
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
+
702
826
  // Corresponds to ReactFiberWakeable and ReactFizzWakeable modules. Generally,
703
827
  // changes to one module should be reflected in the others.
704
828
  // TODO: Rename this module and the corresponding Fiber one to "Thenable"
@@ -827,13 +951,16 @@ function prepareToUseHooksForComponent(prevThenableState) {
827
951
  thenableState = prevThenableState;
828
952
  }
829
953
  function getThenableStateAfterSuspending() {
830
- // If you use() to Suspend this should always exist but if you throw a Promise instead,
831
- // which is not really supported anymore, it will be empty. We use the empty set as a
832
- // marker to know if this was a replay of the same component or first attempt.
833
- const state = thenableState || createThenableState();
954
+ const state = thenableState;
834
955
  thenableState = null;
835
956
  return state;
836
957
  }
958
+
959
+ function readContext(context) {
960
+
961
+ return readContext$1(context);
962
+ }
963
+
837
964
  const HooksDispatcher = {
838
965
  useMemo(nextCreate) {
839
966
  return nextCreate();
@@ -847,8 +974,8 @@ const HooksDispatcher = {
847
974
 
848
975
  useDeferredValue: unsupportedHook,
849
976
  useTransition: unsupportedHook,
850
- readContext: unsupportedContext,
851
- useContext: unsupportedContext,
977
+ readContext,
978
+ useContext: readContext,
852
979
  useReducer: unsupportedHook,
853
980
  useRef: unsupportedHook,
854
981
  useState: unsupportedHook,
@@ -884,10 +1011,6 @@ function unsupportedRefresh() {
884
1011
  throw new Error('Refreshing the cache is not supported in Server Components.');
885
1012
  }
886
1013
 
887
- function unsupportedContext() {
888
- throw new Error('Cannot read a Client Context from a Server Component.');
889
- }
890
-
891
1014
  function useId() {
892
1015
  if (currentRequest$1 === null) {
893
1016
  throw new Error('useId can only be used while React is rendering');
@@ -913,22 +1036,14 @@ function use(usable) {
913
1036
  }
914
1037
 
915
1038
  return trackUsedThenable(thenableState, thenable, index);
916
- } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {
917
- unsupportedContext();
1039
+ } else if (usable.$$typeof === REACT_SERVER_CONTEXT_TYPE) {
1040
+ const context = usable;
1041
+ return readContext(context);
918
1042
  }
919
1043
  }
920
1044
 
921
- if (isClientReference(usable)) {
922
- if (usable.value != null && usable.value.$$typeof === REACT_CONTEXT_TYPE) {
923
- // Show a more specific message since it's a common mistake.
924
- throw new Error('Cannot read a Client Context from a Server Component.');
925
- } else {
926
- throw new Error('Cannot use() an already resolved Client Reference.');
927
- }
928
- } else {
929
- throw new Error( // eslint-disable-next-line react-internal/safe-string-coercion
930
- 'An unsupported type was passed to use(): ' + String(usable));
931
- }
1045
+
1046
+ throw new Error('An unsupported type was passed to use(): ' + String(usable));
932
1047
  }
933
1048
 
934
1049
  function createSignal() {
@@ -1007,10 +1122,6 @@ function describeValueForErrorMessage(value) {
1007
1122
  return '[...]';
1008
1123
  }
1009
1124
 
1010
- if (value !== null && value.$$typeof === CLIENT_REFERENCE_TAG) {
1011
- return describeClientReference();
1012
- }
1013
-
1014
1125
  const name = objectName(value);
1015
1126
 
1016
1127
  if (name === 'Object') {
@@ -1021,14 +1132,7 @@ function describeValueForErrorMessage(value) {
1021
1132
  }
1022
1133
 
1023
1134
  case 'function':
1024
- {
1025
- if (value.$$typeof === CLIENT_REFERENCE_TAG) {
1026
- return describeClientReference();
1027
- }
1028
-
1029
- const name = value.displayName || value.name;
1030
- return name ? 'function ' + name : 'function';
1031
- }
1135
+ return 'function';
1032
1136
 
1033
1137
  default:
1034
1138
  // eslint-disable-next-line react-internal/safe-string-coercion
@@ -1074,12 +1178,6 @@ function describeElementType(type) {
1074
1178
  return '';
1075
1179
  }
1076
1180
 
1077
- const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
1078
-
1079
- function describeClientReference(ref) {
1080
- return 'client';
1081
- }
1082
-
1083
1181
  function describeObjectForErrorMessage(objectOrArray, expandedName) {
1084
1182
  const objKind = objectName(objectOrArray);
1085
1183
 
@@ -1127,8 +1225,6 @@ function describeObjectForErrorMessage(objectOrArray, expandedName) {
1127
1225
  } else {
1128
1226
  if (objectOrArray.$$typeof === REACT_ELEMENT_TYPE) {
1129
1227
  str = '<' + describeElementType(objectOrArray.type) + '/>';
1130
- } else if (objectOrArray.$$typeof === CLIENT_REFERENCE_TAG) {
1131
- return describeClientReference();
1132
1228
  } else {
1133
1229
  // Print Object
1134
1230
  str = '{';
@@ -1208,7 +1304,7 @@ function defaultPostponeHandler(reason) {// Noop
1208
1304
  const OPEN = 0;
1209
1305
  const CLOSING = 1;
1210
1306
  const CLOSED = 2;
1211
- function createRequest(model, bundlerConfig, onError, identifierPrefix, onPostpone, environmentName) {
1307
+ function createRequest(model, bundlerConfig, onError, context, identifierPrefix, onPostpone) {
1212
1308
  if (ReactCurrentCache.current !== null && ReactCurrentCache.current !== DefaultCacheDispatcher) {
1213
1309
  throw new Error('Currently React only supports one RSC renderer at a time.');
1214
1310
  }
@@ -1239,15 +1335,21 @@ function createRequest(model, bundlerConfig, onError, identifierPrefix, onPostpo
1239
1335
  writtenSymbols: new Map(),
1240
1336
  writtenClientReferences: new Map(),
1241
1337
  writtenServerReferences: new Map(),
1338
+ writtenProviders: new Map(),
1242
1339
  writtenObjects: new WeakMap(),
1243
1340
  identifierPrefix: identifierPrefix || '',
1244
1341
  identifierCount: 1,
1245
1342
  taintCleanupQueue: cleanupQueue,
1246
1343
  onError: onError === undefined ? defaultErrorHandler : onError,
1247
- 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
+ }
1248
1349
  };
1249
-
1250
- const rootTask = createTask(request, model, null, false, abortSet);
1350
+ request.pendingChunks++;
1351
+ const rootContext = createRootContext();
1352
+ const rootTask = createTask(request, model, rootContext, abortSet);
1251
1353
  pingedTasks.push(rootTask);
1252
1354
  return request;
1253
1355
  }
@@ -1263,9 +1365,13 @@ function resolveRequest() {
1263
1365
  return null;
1264
1366
  }
1265
1367
 
1266
- function serializeThenable(request, task, thenable) {
1267
- const newTask = createTask(request, null, task.keyPath, // the server component sequence continues through Promise-as-a-child.
1268
- 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);
1269
1375
 
1270
1376
  switch (thenable.status) {
1271
1377
  case 'fulfilled':
@@ -1399,117 +1505,61 @@ function createLazyWrapperAroundWakeable(wakeable) {
1399
1505
  _payload: thenable,
1400
1506
  _init: readThenable
1401
1507
  };
1402
-
1403
1508
  return lazyType;
1404
1509
  }
1405
1510
 
1406
- function renderFunctionComponent(request, task, key, Component, props) {
1407
- // Reset the task's thenable state before continuing, so that if a later
1408
- // component suspends we can reuse the same task object. If the same
1409
- // component suspends again, the thenable state will be restored.
1410
- const prevThenableState = task.thenableState;
1411
- task.thenableState = null;
1412
-
1413
- prepareToUseHooksForComponent(prevThenableState); // The secondArg is always undefined in Server Components since refs error early.
1414
-
1415
- const secondArg = undefined;
1416
- let result = Component(props, secondArg);
1417
-
1418
- if (typeof result === 'object' && result !== null && typeof result.then === 'function') {
1419
- // When the return value is in children position we can resolve it immediately,
1420
- // to its value without a wrapper if it's synchronously available.
1421
- const thenable = result;
1422
-
1423
- if (thenable.status === 'fulfilled') {
1424
- return thenable.value;
1425
- } // TODO: Once we accept Promises as children on the client, we can just return
1426
- // the thenable here.
1427
-
1428
-
1429
- result = createLazyWrapperAroundWakeable(result);
1430
- } // Track this element's key on the Server Component on the keyPath context..
1431
-
1432
-
1433
- const prevKeyPath = task.keyPath;
1434
- const prevImplicitSlot = task.implicitSlot;
1435
-
1436
- if (key !== null) {
1437
- // Append the key to the path. Technically a null key should really add the child
1438
- // index. We don't do that to hold the payload small and implementation simple.
1439
- task.keyPath = prevKeyPath === null ? key : prevKeyPath + ',' + key;
1440
- } else if (prevKeyPath === null) {
1441
- // This sequence of Server Components has no keys. This means that it was rendered
1442
- // in a slot that needs to assign an implicit key. Even if children below have
1443
- // explicit keys, they should not be used for the outer most key since it might
1444
- // collide with other slots in that set.
1445
- task.implicitSlot = true;
1446
- }
1447
-
1448
- const json = renderModelDestructive(request, task, emptyRoot, '', result);
1449
- task.keyPath = prevKeyPath;
1450
- task.implicitSlot = prevImplicitSlot;
1451
- return json;
1452
- }
1453
-
1454
- function renderFragment(request, task, children) {
1455
-
1456
- {
1457
- return children;
1458
- }
1459
- }
1460
-
1461
- function renderClientElement(task, type, key, props) {
1462
- {
1463
- return [REACT_ELEMENT_TYPE, type, key, props];
1464
- } // We prepend the terminal client element that actually gets serialized with
1465
- } // The chunk ID we're currently rendering that we can assign debug data to.
1466
-
1467
-
1468
- let debugID = null;
1469
-
1470
- function renderElement(request, task, type, key, ref, props) {
1511
+ function attemptResolveElement(request, type, key, ref, props, prevThenableState) {
1471
1512
  if (ref !== null && ref !== undefined) {
1472
1513
  // When the ref moves to the regular props object this will implicitly
1473
1514
  // throw for functions. We could probably relax it to a DEV warning for other
1474
1515
  // cases.
1475
- // TODO: `ref` is now just a prop when `enableRefAsProp` is on. Should we
1476
- // do what the above comment says?
1477
1516
  throw new Error('Refs cannot be used in Server Components, nor passed to Client Components.');
1478
1517
  }
1479
1518
 
1480
1519
  if (typeof type === 'function') {
1481
1520
  if (isClientReference(type)) {
1482
1521
  // This is a reference to a Client Component.
1483
- return renderClientElement(task, type, key, props);
1484
- } // This is a Server Component.
1522
+ return [REACT_ELEMENT_TYPE, type, key, props];
1523
+ } // This is a server-side component.
1524
+
1525
+
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
+
1485
1539
 
1540
+ return createLazyWrapperAroundWakeable(result);
1541
+ }
1486
1542
 
1487
- return renderFunctionComponent(request, task, key, type, props);
1543
+ return result;
1488
1544
  } else if (typeof type === 'string') {
1489
1545
  // This is a host element. E.g. HTML.
1490
- return renderClientElement(task, type, key, props);
1546
+ return [REACT_ELEMENT_TYPE, type, key, props];
1491
1547
  } else if (typeof type === 'symbol') {
1492
- if (type === REACT_FRAGMENT_TYPE && key === null) {
1548
+ if (type === REACT_FRAGMENT_TYPE) {
1493
1549
  // For key-less fragments, we add a small optimization to avoid serializing
1494
1550
  // it as a wrapper.
1495
- const prevImplicitSlot = task.implicitSlot;
1496
-
1497
- if (task.keyPath === null) {
1498
- task.implicitSlot = true;
1499
- }
1500
-
1501
- const json = renderModelDestructive(request, task, emptyRoot, '', props.children);
1502
- task.implicitSlot = prevImplicitSlot;
1503
- 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;
1504
1554
  } // This might be a built-in React component. We'll let the client decide.
1505
1555
  // Any built-in works as long as its props are serializable.
1506
1556
 
1507
1557
 
1508
- return renderClientElement(task, type, key, props);
1558
+ return [REACT_ELEMENT_TYPE, type, key, props];
1509
1559
  } else if (type != null && typeof type === 'object') {
1510
1560
  if (isClientReference(type)) {
1511
1561
  // This is a reference to a Client Component.
1512
- return renderClientElement(task, type, key, props);
1562
+ return [REACT_ELEMENT_TYPE, type, key, props];
1513
1563
  }
1514
1564
 
1515
1565
  switch (type.$$typeof) {
@@ -1518,17 +1568,19 @@ function renderElement(request, task, type, key, ref, props) {
1518
1568
  const payload = type._payload;
1519
1569
  const init = type._init;
1520
1570
  const wrappedType = init(payload);
1521
- return renderElement(request, task, wrappedType, key, ref, props);
1571
+ return attemptResolveElement(request, wrappedType, key, ref, props, prevThenableState);
1522
1572
  }
1523
1573
 
1524
1574
  case REACT_FORWARD_REF_TYPE:
1525
1575
  {
1526
- return renderFunctionComponent(request, task, key, type.render, props);
1576
+ const render = type.render;
1577
+ prepareToUseHooksForComponent(prevThenableState);
1578
+ return render(props, undefined);
1527
1579
  }
1528
1580
 
1529
1581
  case REACT_MEMO_TYPE:
1530
1582
  {
1531
- return renderElement(request, task, type.type, key, ref, props);
1583
+ return attemptResolveElement(request, type.type, key, ref, props, prevThenableState);
1532
1584
  }
1533
1585
  }
1534
1586
  }
@@ -1546,30 +1598,14 @@ function pingTask(request, task) {
1546
1598
  }
1547
1599
  }
1548
1600
 
1549
- function createTask(request, model, keyPath, implicitSlot, abortSet) {
1550
- request.pendingChunks++;
1601
+ function createTask(request, model, context, abortSet) {
1551
1602
  const id = request.nextChunkId++;
1552
-
1553
- if (typeof model === 'object' && model !== null) {
1554
- // If we're about to write this into a new task we can assign it an ID early so that
1555
- // any other references can refer to the value we're about to write.
1556
- {
1557
- request.writtenObjects.set(model, id);
1558
- }
1559
- }
1560
-
1561
1603
  const task = {
1562
1604
  id,
1563
1605
  status: PENDING$1,
1564
1606
  model,
1565
- keyPath,
1566
- implicitSlot,
1607
+ context,
1567
1608
  ping: () => pingTask(request, task),
1568
- toJSON: function (parentPropertyName, value) {
1569
- const parent = this; // Make sure that `parent[parentPropertyName]` wasn't JSONified before `value` was passed to us
1570
-
1571
- return renderModel(request, task, parent, parentPropertyName, value);
1572
- },
1573
1609
  thenableState: null
1574
1610
  };
1575
1611
  abortSet.add(task);
@@ -1638,13 +1674,13 @@ function encodeReferenceChunk(request, id, reference) {
1638
1674
  return stringToChunk(row);
1639
1675
  }
1640
1676
 
1641
- function serializeClientReference(request, parent, parentPropertyName, clientReference) {
1677
+ function serializeClientReference(request, parent, key, clientReference) {
1642
1678
  const clientReferenceKey = getClientReferenceKey(clientReference);
1643
1679
  const writtenClientReferences = request.writtenClientReferences;
1644
1680
  const existingId = writtenClientReferences.get(clientReferenceKey);
1645
1681
 
1646
1682
  if (existingId !== undefined) {
1647
- if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {
1683
+ if (parent[0] === REACT_ELEMENT_TYPE && key === '1') {
1648
1684
  // If we're encoding the "type" of an element, we can refer
1649
1685
  // to that by a lazy reference instead of directly since React
1650
1686
  // knows how to deal with lazy values. This lets us suspend
@@ -1663,7 +1699,7 @@ function serializeClientReference(request, parent, parentPropertyName, clientRef
1663
1699
  emitImportChunk(request, importId, clientReferenceMetadata);
1664
1700
  writtenClientReferences.set(clientReferenceKey, importId);
1665
1701
 
1666
- if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {
1702
+ if (parent[0] === REACT_ELEMENT_TYPE && key === '1') {
1667
1703
  // If we're encoding the "type" of an element, we can refer
1668
1704
  // to that by a lazy reference instead of directly since React
1669
1705
  // knows how to deal with lazy values. This lets us suspend
@@ -1683,14 +1719,13 @@ function serializeClientReference(request, parent, parentPropertyName, clientRef
1683
1719
  }
1684
1720
 
1685
1721
  function outlineModel(request, value) {
1686
- const newTask = createTask(request, value, null, // The way we use outlining is for reusing an object.
1687
- false, // It makes no sense for that use case to be contextual.
1688
- request.abortableTasks);
1722
+ request.pendingChunks++;
1723
+ const newTask = createTask(request, value, getActiveContext(), request.abortableTasks);
1689
1724
  retryTask(request, newTask);
1690
1725
  return newTask.id;
1691
1726
  }
1692
1727
 
1693
- function serializeServerReference(request, serverReference) {
1728
+ function serializeServerReference(request, parent, key, serverReference) {
1694
1729
  const writtenServerReferences = request.writtenServerReferences;
1695
1730
  const existingId = writtenServerReferences.get(serverReference);
1696
1731
 
@@ -1770,77 +1805,91 @@ function escapeStringValue(value) {
1770
1805
  return value;
1771
1806
  }
1772
1807
  }
1773
-
1774
1808
  let modelRoot = false;
1775
1809
 
1776
- function renderModel(request, task, parent, key, value) {
1777
- const prevKeyPath = task.keyPath;
1778
- const prevImplicitSlot = task.implicitSlot;
1810
+ function resolveModelToJSON(request, parent, key, value) {
1779
1811
 
1780
- try {
1781
- return renderModelDestructive(request, task, parent, key, value);
1782
- } catch (thrownValue) {
1783
- const x = thrownValue === SuspenseException ? // This is a special type of exception used for Suspense. For historical
1784
- // reasons, the rest of the Suspense implementation expects the thrown
1785
- // value to be a thenable, because before `use` existed that was the
1786
- // (unstable) API for suspending. This implementation detail can change
1787
- // later, once we deprecate the old API in favor of `use`.
1788
- getSuspendedThenable() : thrownValue; // If the suspended/errored value was an element or lazy it can be reduced
1789
- // to a lazy reference, so that it doesn't error the parent.
1790
1812
 
1791
- const model = task.model;
1792
- 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
+ }
1793
1817
 
1794
- if (typeof x === 'object' && x !== null) {
1795
- // $FlowFixMe[method-unbinding]
1796
- if (typeof x.then === 'function') {
1797
- // Something suspended, we'll need to create a new task and resolve it later.
1798
- const newTask = createTask(request, task.model, task.keyPath, task.implicitSlot, request.abortableTasks);
1799
- const ping = newTask.ping;
1800
- x.then(ping, ping);
1801
- newTask.thenableState = getThenableStateAfterSuspending(); // Restore the context. We assume that this will be restored by the inner
1802
- // functions in case nothing throws so we don't use "finally" here.
1803
1818
 
1804
- task.keyPath = prevKeyPath;
1805
- task.implicitSlot = prevImplicitSlot;
1819
+ while (typeof value === 'object' && value !== null && (value.$$typeof === REACT_ELEMENT_TYPE || value.$$typeof === REACT_LAZY_TYPE)) {
1806
1820
 
1807
- if (wasReactNode) {
1808
- return serializeLazyID(newTask.id);
1809
- }
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.
1810
1847
 
1811
- return serializeByValueID(newTask.id);
1812
- }
1813
- } // Restore the context. We assume that this will be restored by the inner
1814
- // functions in case nothing throws so we don't use "finally" here.
1815
1848
 
1849
+ const element = value; // Attempt to render the Server Component.
1816
1850
 
1817
- task.keyPath = prevKeyPath;
1818
- task.implicitSlot = prevImplicitSlot;
1851
+ value = attemptResolveElement(request, element.type, element.key, element.ref, element.props, null);
1852
+ break;
1853
+ }
1819
1854
 
1820
- if (wasReactNode) {
1821
- // 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.
1822
1883
  // We'll replace this element with a lazy reference that throws on the client
1823
1884
  // once it gets rendered.
1885
+
1886
+
1824
1887
  request.pendingChunks++;
1825
1888
  const errorId = request.nextChunkId++;
1826
1889
  const digest = logRecoverableError(request, x);
1827
1890
  emitErrorChunk(request, errorId, digest);
1828
1891
  return serializeLazyID(errorId);
1829
- } // Something errored but it was not in a React Node. There's no need to serialize
1830
- // it by value because it'll just error the whole parent row anyway so we can
1831
- // just stop any siblings and error the whole parent row.
1832
-
1833
-
1834
- throw x;
1835
- }
1836
- }
1837
-
1838
- function renderModelDestructive(request, task, parent, parentPropertyName, value) {
1839
- // Set the currently rendering model
1840
- task.model = value; // Special Symbol, that's very common.
1841
-
1842
- if (value === REACT_ELEMENT_TYPE) {
1843
- return '$';
1892
+ }
1844
1893
  }
1845
1894
 
1846
1895
  if (value === null) {
@@ -1848,70 +1897,9 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1848
1897
  }
1849
1898
 
1850
1899
  if (typeof value === 'object') {
1851
- switch (value.$$typeof) {
1852
- case REACT_ELEMENT_TYPE:
1853
- {
1854
- const writtenObjects = request.writtenObjects;
1855
- const existingId = writtenObjects.get(value);
1856
-
1857
- if (existingId !== undefined) {
1858
- if (modelRoot === value) {
1859
- // This is the ID we're currently emitting so we need to write it
1860
- // once but if we discover it again, we refer to it by id.
1861
- modelRoot = null;
1862
- } else if (existingId === -1) {
1863
- // Seen but not yet outlined.
1864
- // TODO: If we throw here we can treat this as suspending which causes an outline
1865
- // but that is able to reuse the same task if we're already in one but then that
1866
- // will be a lazy future value rather than guaranteed to exist but maybe that's good.
1867
- const newId = outlineModel(request, value);
1868
- return serializeByValueID(newId);
1869
- } else {
1870
- // We've already emitted this as an outlined object, so we can refer to that by its
1871
- // existing ID. TODO: We should use a lazy reference since, unlike plain objects,
1872
- // elements might suspend so it might not have emitted yet even if we have the ID for
1873
- // it. However, this creates an extra wrapper when it's not needed. We should really
1874
- // detect whether this already was emitted and synchronously available. In that
1875
- // case we can refer to it synchronously and only make it lazy otherwise.
1876
- // We currently don't have a data structure that lets us see that though.
1877
- return serializeByValueID(existingId);
1878
- }
1879
- } else {
1880
- // This is the first time we've seen this object. We may never see it again
1881
- // so we'll inline it. Mark it as seen. If we see it again, we'll outline.
1882
- writtenObjects.set(value, -1);
1883
- }
1884
-
1885
- const element = value;
1886
-
1887
- const props = element.props;
1888
- let ref;
1889
-
1890
- {
1891
- ref = element.ref;
1892
- } // Attempt to render the Server Component.
1893
-
1894
-
1895
- return renderElement(request, task, element.type, // $FlowFixMe[incompatible-call] the key of an element is null | string
1896
- element.key, ref, props);
1897
- }
1898
-
1899
- case REACT_LAZY_TYPE:
1900
- {
1901
- // Reset the task's thenable state before continuing. If there was one, it was
1902
- // from suspending the lazy before.
1903
- task.thenableState = null;
1904
- const lazy = value;
1905
- const payload = lazy._payload;
1906
- const init = lazy._init;
1907
- const resolvedModel = init(payload);
1908
-
1909
- return renderModelDestructive(request, task, emptyRoot, '', resolvedModel);
1910
- }
1911
- }
1912
1900
 
1913
1901
  if (isClientReference(value)) {
1914
- return serializeClientReference(request, parent, parentPropertyName, value);
1902
+ return serializeClientReference(request, parent, key, value);
1915
1903
  }
1916
1904
 
1917
1905
  const writtenObjects = request.writtenObjects;
@@ -1931,20 +1919,20 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1931
1919
  // or a Promise type. Either of which can be represented by a Promise.
1932
1920
 
1933
1921
 
1934
- const promiseId = serializeThenable(request, task, value);
1922
+ const promiseId = serializeThenable(request, value);
1935
1923
  writtenObjects.set(value, promiseId);
1936
1924
  return serializePromiseID(promiseId);
1937
1925
  }
1938
1926
 
1939
1927
  if (existingId !== undefined) {
1940
- if (modelRoot === value) {
1941
- // This is the ID we're currently emitting so we need to write it
1942
- // once but if we discover it again, we refer to it by id.
1943
- modelRoot = null;
1944
- } else if (existingId === -1) {
1928
+ if (existingId === -1) {
1945
1929
  // Seen but not yet outlined.
1946
1930
  const newId = outlineModel(request, value);
1947
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;
1948
1936
  } else {
1949
1937
  // We've already emitted this as an outlined object, so we can
1950
1938
  // just refer to that by its existing ID.
@@ -1957,7 +1945,8 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1957
1945
  }
1958
1946
 
1959
1947
  if (isArray(value)) {
1960
- return renderFragment(request, task, value);
1948
+ // $FlowFixMe[incompatible-return]
1949
+ return value;
1961
1950
  }
1962
1951
 
1963
1952
  if (value instanceof Map) {
@@ -1971,7 +1960,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1971
1960
  const iteratorFn = getIteratorFn(value);
1972
1961
 
1973
1962
  if (iteratorFn) {
1974
- return renderFragment(request, task, Array.from(value));
1963
+ return Array.from(value);
1975
1964
  } // Verify that this is a simple plain object.
1976
1965
 
1977
1966
 
@@ -1991,7 +1980,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1991
1980
  if (value[value.length - 1] === 'Z') {
1992
1981
  // Possibly a Date, whose toJSON automatically calls toISOString
1993
1982
  // $FlowFixMe[incompatible-use]
1994
- const originalValue = parent[parentPropertyName];
1983
+ const originalValue = parent[key];
1995
1984
 
1996
1985
  if (originalValue instanceof Date) {
1997
1986
  return serializeDateFromDateJSON(value);
@@ -2021,18 +2010,19 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2021
2010
  }
2022
2011
 
2023
2012
  if (typeof value === 'function') {
2013
+
2024
2014
  if (isClientReference(value)) {
2025
- return serializeClientReference(request, parent, parentPropertyName, value);
2015
+ return serializeClientReference(request, parent, key, value);
2026
2016
  }
2027
2017
 
2028
2018
  if (isServerReference(value)) {
2029
- return serializeServerReference(request, value);
2019
+ return serializeServerReference(request, parent, key, value);
2030
2020
  }
2031
2021
 
2032
- if (/^on[A-Z]/.test(parentPropertyName)) {
2033
- 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.');
2034
2024
  } else {
2035
- 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));
2036
2026
  }
2037
2027
  }
2038
2028
 
@@ -2049,7 +2039,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2049
2039
 
2050
2040
  if (Symbol.for(name) !== value) {
2051
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
2052
- value.description + ") cannot be found among global symbols.") + describeObjectForErrorMessage(parent, parentPropertyName));
2042
+ value.description + ") cannot be found among global symbols.") + describeObjectForErrorMessage(parent, key));
2053
2043
  }
2054
2044
 
2055
2045
  request.pendingChunks++;
@@ -2064,44 +2054,17 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2064
2054
  return serializeBigInt(value);
2065
2055
  }
2066
2056
 
2067
- 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));
2068
2058
  }
2069
2059
 
2070
2060
  function logPostpone(request, reason) {
2071
- const prevRequest = currentRequest;
2072
- currentRequest = null;
2073
-
2074
- try {
2075
- const onPostpone = request.onPostpone;
2076
-
2077
- if (supportsRequestStorage) {
2078
- // Exit the request context while running callbacks.
2079
- requestStorage.run(undefined, onPostpone, reason);
2080
- } else {
2081
- onPostpone(reason);
2082
- }
2083
- } finally {
2084
- currentRequest = prevRequest;
2085
- }
2061
+ const onPostpone = request.onPostpone;
2062
+ onPostpone(reason);
2086
2063
  }
2087
2064
 
2088
2065
  function logRecoverableError(request, error) {
2089
- const prevRequest = currentRequest;
2090
- currentRequest = null;
2091
- let errorDigest;
2092
-
2093
- try {
2094
- const onError = request.onError;
2095
-
2096
- if (supportsRequestStorage) {
2097
- // Exit the request context while running callbacks.
2098
- errorDigest = requestStorage.run(undefined, onError, error);
2099
- } else {
2100
- errorDigest = onError(error);
2101
- }
2102
- } finally {
2103
- currentRequest = prevRequest;
2104
- }
2066
+ const onError = request.onError;
2067
+ const errorDigest = onError(error);
2105
2068
 
2106
2069
  if (errorDigest != null && typeof errorDigest !== 'string') {
2107
2070
  // eslint-disable-next-line react-internal/prod-error-codes
@@ -2171,54 +2134,62 @@ function emitSymbolChunk(request, id, name) {
2171
2134
  request.completedImportChunks.push(processedChunk);
2172
2135
  }
2173
2136
 
2174
- 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);
2175
2144
  const row = id.toString(16) + ':' + json + '\n';
2176
2145
  const processedChunk = stringToChunk(row);
2177
2146
  request.completedRegularChunks.push(processedChunk);
2178
2147
  }
2179
2148
 
2180
- const emptyRoot = {};
2181
-
2182
2149
  function retryTask(request, task) {
2183
2150
  if (task.status !== PENDING$1) {
2184
2151
  // We completed this by other means before we had a chance to retry it.
2185
2152
  return;
2186
2153
  }
2187
2154
 
2155
+ switchContext(task.context);
2156
+
2188
2157
  try {
2189
- // Track the root so we know that we have to emit this object even though it
2190
- // already has an ID. This is needed because we might see this object twice
2191
- // in the same toJSON if it is cyclic.
2192
- modelRoot = task.model;
2158
+ let value = task.model;
2193
2159
 
2194
- if (false) ; // We call the destructive form that mutates this task. That way if something
2195
- // 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.
2196
2162
 
2163
+ const element = value; // When retrying a component, reuse the thenableState from the
2164
+ // previous attempt.
2197
2165
 
2198
- 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.
2199
2169
 
2200
- 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.
2201
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.
2202
2177
 
2203
- 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.
2204
2180
 
2205
- task.keyPath = null;
2206
- task.implicitSlot = false;
2207
- 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.
2208
2186
 
2209
- if (typeof resolvedModel === 'object' && resolvedModel !== null) {
2210
- // Object might contain unresolved values like additional elements.
2211
- // This is simulating what the JSON loop would do if this was part of it.
2212
- // $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do
2213
- json = stringify(resolvedModel, task.toJSON);
2214
- } else {
2215
- // If the value is a string, it means it's a terminal value and we already escaped it
2216
- // We don't need to escape it again so it's not passed the toJSON replacer.
2217
- // $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do
2218
- json = stringify(resolvedModel);
2187
+
2188
+ if (typeof value === 'object' && value !== null) {
2189
+ request.writtenObjects.set(value, task.id);
2219
2190
  }
2220
2191
 
2221
- emitModelChunk(request, task.id, json);
2192
+ emitModelChunk(request, task.id, value);
2222
2193
  request.abortableTasks.delete(task);
2223
2194
  task.status = COMPLETED;
2224
2195
  } catch (thrownValue) {
@@ -2244,7 +2215,6 @@ function retryTask(request, task) {
2244
2215
  task.status = ERRORED$1;
2245
2216
  const digest = logRecoverableError(request, x);
2246
2217
  emitErrorChunk(request, task.id, digest);
2247
- } finally {
2248
2218
  }
2249
2219
  }
2250
2220
 
@@ -2434,6 +2404,11 @@ function abort(request, reason) {
2434
2404
  }
2435
2405
  }
2436
2406
 
2407
+ function importServerContexts(contexts) {
2408
+
2409
+ return rootContextSnapshot;
2410
+ }
2411
+
2437
2412
  // This is the parsed shape of the wire format which is why it is
2438
2413
  // condensed to only the essentialy information
2439
2414
  const ID = 0;
@@ -3120,7 +3095,7 @@ function decodeFormState(actionResult, body, serverManifest) {
3120
3095
  }
3121
3096
 
3122
3097
  function renderToReadableStream(model, webpackMap, options) {
3123
- 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);
3124
3099
 
3125
3100
  if (options && options.signal) {
3126
3101
  const signal = options.signal;