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
@@ -10,8 +10,8 @@
10
10
 
11
11
  'use strict';
12
12
 
13
- var React = require('react');
14
13
  var ReactDOM = require('react-dom');
14
+ var React = require('react');
15
15
 
16
16
  // -----------------------------------------------------------------------------
17
17
  const enablePostpone = false;
@@ -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) {
@@ -656,16 +640,13 @@ function createHints() {
656
640
  return new Set();
657
641
  }
658
642
 
659
- const supportsRequestStorage = false;
660
- const requestStorage = null;
661
-
662
643
  // ATTENTION
663
644
  // When adding new symbols to this file,
664
645
  // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
665
646
  // The Symbol used to tag the ReactElement-like types.
666
647
  const REACT_ELEMENT_TYPE = Symbol.for('react.element');
667
648
  const REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
668
- const REACT_CONTEXT_TYPE = Symbol.for('react.context');
649
+ const REACT_SERVER_CONTEXT_TYPE = Symbol.for('react.server_context');
669
650
  const REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
670
651
  const REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
671
652
  const REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
@@ -689,6 +670,146 @@ function getIteratorFn(maybeIterable) {
689
670
  return null;
690
671
  }
691
672
 
673
+ // Forming a reverse tree.
674
+ // The structure of a context snapshot is an implementation of this file.
675
+ // Currently, it's implemented as tracking the current active node.
676
+
677
+
678
+ const rootContextSnapshot = null; // We assume that this runtime owns the "current" field on all ReactContext instances.
679
+ // This global (actually thread local) state represents what state all those "current",
680
+ // fields are currently in.
681
+
682
+ let currentActiveSnapshot = null;
683
+
684
+ function popNode(prev) {
685
+ {
686
+ prev.context._currentValue = prev.parentValue;
687
+ }
688
+ }
689
+
690
+ function pushNode(next) {
691
+ {
692
+ next.context._currentValue = next.value;
693
+ }
694
+ }
695
+
696
+ function popToNearestCommonAncestor(prev, next) {
697
+ if (prev === next) ; else {
698
+ popNode(prev);
699
+ const parentPrev = prev.parent;
700
+ const parentNext = next.parent;
701
+
702
+ if (parentPrev === null) {
703
+ if (parentNext !== null) {
704
+ throw new Error('The stacks must reach the root at the same time. This is a bug in React.');
705
+ }
706
+ } else {
707
+ if (parentNext === null) {
708
+ throw new Error('The stacks must reach the root at the same time. This is a bug in React.');
709
+ }
710
+
711
+ popToNearestCommonAncestor(parentPrev, parentNext); // On the way back, we push the new ones that weren't common.
712
+
713
+ pushNode(next);
714
+ }
715
+ }
716
+ }
717
+
718
+ function popAllPrevious(prev) {
719
+ popNode(prev);
720
+ const parentPrev = prev.parent;
721
+
722
+ if (parentPrev !== null) {
723
+ popAllPrevious(parentPrev);
724
+ }
725
+ }
726
+
727
+ function pushAllNext(next) {
728
+ const parentNext = next.parent;
729
+
730
+ if (parentNext !== null) {
731
+ pushAllNext(parentNext);
732
+ }
733
+
734
+ pushNode(next);
735
+ }
736
+
737
+ function popPreviousToCommonLevel(prev, next) {
738
+ popNode(prev);
739
+ const parentPrev = prev.parent;
740
+
741
+ if (parentPrev === null) {
742
+ throw new Error('The depth must equal at least at zero before reaching the root. This is a bug in React.');
743
+ }
744
+
745
+ if (parentPrev.depth === next.depth) {
746
+ // We found the same level. Now we just need to find a shared ancestor.
747
+ popToNearestCommonAncestor(parentPrev, next);
748
+ } else {
749
+ // We must still be deeper.
750
+ popPreviousToCommonLevel(parentPrev, next);
751
+ }
752
+ }
753
+
754
+ function popNextToCommonLevel(prev, next) {
755
+ const parentNext = next.parent;
756
+
757
+ if (parentNext === null) {
758
+ throw new Error('The depth must equal at least at zero before reaching the root. This is a bug in React.');
759
+ }
760
+
761
+ if (prev.depth === parentNext.depth) {
762
+ // We found the same level. Now we just need to find a shared ancestor.
763
+ popToNearestCommonAncestor(prev, parentNext);
764
+ } else {
765
+ // We must still be deeper.
766
+ popNextToCommonLevel(prev, parentNext);
767
+ }
768
+
769
+ pushNode(next);
770
+ } // Perform context switching to the new snapshot.
771
+ // To make it cheap to read many contexts, while not suspending, we make the switch eagerly by
772
+ // updating all the context's current values. That way reads, always just read the current value.
773
+ // At the cost of updating contexts even if they're never read by this subtree.
774
+
775
+
776
+ function switchContext(newSnapshot) {
777
+ // The basic algorithm we need to do is to pop back any contexts that are no longer on the stack.
778
+ // We also need to update any new contexts that are now on the stack with the deepest value.
779
+ // The easiest way to update new contexts is to just reapply them in reverse order from the
780
+ // perspective of the backpointers. To avoid allocating a lot when switching, we use the stack
781
+ // for that. Therefore this algorithm is recursive.
782
+ // 1) First we pop which ever snapshot tree was deepest. Popping old contexts as we go.
783
+ // 2) Then we find the nearest common ancestor from there. Popping old contexts as we go.
784
+ // 3) Then we reapply new contexts on the way back up the stack.
785
+ const prev = currentActiveSnapshot;
786
+ const next = newSnapshot;
787
+
788
+ if (prev !== next) {
789
+ if (prev === null) {
790
+ // $FlowFixMe[incompatible-call]: This has to be non-null since it's not equal to prev.
791
+ pushAllNext(next);
792
+ } else if (next === null) {
793
+ popAllPrevious(prev);
794
+ } else if (prev.depth === next.depth) {
795
+ popToNearestCommonAncestor(prev, next);
796
+ } else if (prev.depth > next.depth) {
797
+ popPreviousToCommonLevel(prev, next);
798
+ } else {
799
+ popNextToCommonLevel(prev, next);
800
+ }
801
+
802
+ currentActiveSnapshot = next;
803
+ }
804
+ }
805
+ function getActiveContext() {
806
+ return currentActiveSnapshot;
807
+ }
808
+ function readContext$1(context) {
809
+ const value = context._currentValue ;
810
+ return value;
811
+ }
812
+
692
813
  // Corresponds to ReactFiberWakeable and ReactFizzWakeable modules. Generally,
693
814
  // changes to one module should be reflected in the others.
694
815
  // TODO: Rename this module and the corresponding Fiber one to "Thenable"
@@ -817,13 +938,16 @@ function prepareToUseHooksForComponent(prevThenableState) {
817
938
  thenableState = prevThenableState;
818
939
  }
819
940
  function getThenableStateAfterSuspending() {
820
- // If you use() to Suspend this should always exist but if you throw a Promise instead,
821
- // which is not really supported anymore, it will be empty. We use the empty set as a
822
- // marker to know if this was a replay of the same component or first attempt.
823
- const state = thenableState || createThenableState();
941
+ const state = thenableState;
824
942
  thenableState = null;
825
943
  return state;
826
944
  }
945
+
946
+ function readContext(context) {
947
+
948
+ return readContext$1(context);
949
+ }
950
+
827
951
  const HooksDispatcher = {
828
952
  useMemo(nextCreate) {
829
953
  return nextCreate();
@@ -837,8 +961,8 @@ const HooksDispatcher = {
837
961
 
838
962
  useDeferredValue: unsupportedHook,
839
963
  useTransition: unsupportedHook,
840
- readContext: unsupportedContext,
841
- useContext: unsupportedContext,
964
+ readContext,
965
+ useContext: readContext,
842
966
  useReducer: unsupportedHook,
843
967
  useRef: unsupportedHook,
844
968
  useState: unsupportedHook,
@@ -874,10 +998,6 @@ function unsupportedRefresh() {
874
998
  throw new Error('Refreshing the cache is not supported in Server Components.');
875
999
  }
876
1000
 
877
- function unsupportedContext() {
878
- throw new Error('Cannot read a Client Context from a Server Component.');
879
- }
880
-
881
1001
  function useId() {
882
1002
  if (currentRequest$1 === null) {
883
1003
  throw new Error('useId can only be used while React is rendering');
@@ -903,22 +1023,14 @@ function use(usable) {
903
1023
  }
904
1024
 
905
1025
  return trackUsedThenable(thenableState, thenable, index);
906
- } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {
907
- unsupportedContext();
1026
+ } else if (usable.$$typeof === REACT_SERVER_CONTEXT_TYPE) {
1027
+ const context = usable;
1028
+ return readContext(context);
908
1029
  }
909
1030
  }
910
1031
 
911
- if (isClientReference(usable)) {
912
- if (usable.value != null && usable.value.$$typeof === REACT_CONTEXT_TYPE) {
913
- // Show a more specific message since it's a common mistake.
914
- throw new Error('Cannot read a Client Context from a Server Component.');
915
- } else {
916
- throw new Error('Cannot use() an already resolved Client Reference.');
917
- }
918
- } else {
919
- throw new Error( // eslint-disable-next-line react-internal/safe-string-coercion
920
- 'An unsupported type was passed to use(): ' + String(usable));
921
- }
1032
+
1033
+ throw new Error('An unsupported type was passed to use(): ' + String(usable));
922
1034
  }
923
1035
 
924
1036
  function createSignal() {
@@ -997,10 +1109,6 @@ function describeValueForErrorMessage(value) {
997
1109
  return '[...]';
998
1110
  }
999
1111
 
1000
- if (value !== null && value.$$typeof === CLIENT_REFERENCE_TAG) {
1001
- return describeClientReference();
1002
- }
1003
-
1004
1112
  const name = objectName(value);
1005
1113
 
1006
1114
  if (name === 'Object') {
@@ -1011,14 +1119,7 @@ function describeValueForErrorMessage(value) {
1011
1119
  }
1012
1120
 
1013
1121
  case 'function':
1014
- {
1015
- if (value.$$typeof === CLIENT_REFERENCE_TAG) {
1016
- return describeClientReference();
1017
- }
1018
-
1019
- const name = value.displayName || value.name;
1020
- return name ? 'function ' + name : 'function';
1021
- }
1122
+ return 'function';
1022
1123
 
1023
1124
  default:
1024
1125
  // eslint-disable-next-line react-internal/safe-string-coercion
@@ -1064,12 +1165,6 @@ function describeElementType(type) {
1064
1165
  return '';
1065
1166
  }
1066
1167
 
1067
- const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
1068
-
1069
- function describeClientReference(ref) {
1070
- return 'client';
1071
- }
1072
-
1073
1168
  function describeObjectForErrorMessage(objectOrArray, expandedName) {
1074
1169
  const objKind = objectName(objectOrArray);
1075
1170
 
@@ -1117,8 +1212,6 @@ function describeObjectForErrorMessage(objectOrArray, expandedName) {
1117
1212
  } else {
1118
1213
  if (objectOrArray.$$typeof === REACT_ELEMENT_TYPE) {
1119
1214
  str = '<' + describeElementType(objectOrArray.type) + '/>';
1120
- } else if (objectOrArray.$$typeof === CLIENT_REFERENCE_TAG) {
1121
- return describeClientReference();
1122
1215
  } else {
1123
1216
  // Print Object
1124
1217
  str = '{';
@@ -1198,7 +1291,7 @@ function defaultPostponeHandler(reason) {// Noop
1198
1291
  const OPEN = 0;
1199
1292
  const CLOSING = 1;
1200
1293
  const CLOSED = 2;
1201
- function createRequest(model, bundlerConfig, onError, identifierPrefix, onPostpone, environmentName) {
1294
+ function createRequest(model, bundlerConfig, onError, context, identifierPrefix, onPostpone) {
1202
1295
  if (ReactCurrentCache.current !== null && ReactCurrentCache.current !== DefaultCacheDispatcher) {
1203
1296
  throw new Error('Currently React only supports one RSC renderer at a time.');
1204
1297
  }
@@ -1229,15 +1322,21 @@ function createRequest(model, bundlerConfig, onError, identifierPrefix, onPostpo
1229
1322
  writtenSymbols: new Map(),
1230
1323
  writtenClientReferences: new Map(),
1231
1324
  writtenServerReferences: new Map(),
1325
+ writtenProviders: new Map(),
1232
1326
  writtenObjects: new WeakMap(),
1233
1327
  identifierPrefix: identifierPrefix || '',
1234
1328
  identifierCount: 1,
1235
1329
  taintCleanupQueue: cleanupQueue,
1236
1330
  onError: onError === undefined ? defaultErrorHandler : onError,
1237
- onPostpone: onPostpone === undefined ? defaultPostponeHandler : onPostpone
1331
+ onPostpone: onPostpone === undefined ? defaultPostponeHandler : onPostpone,
1332
+ // $FlowFixMe[missing-this-annot]
1333
+ toJSON: function (key, value) {
1334
+ return resolveModelToJSON(request, this, key, value);
1335
+ }
1238
1336
  };
1239
-
1240
- const rootTask = createTask(request, model, null, false, abortSet);
1337
+ request.pendingChunks++;
1338
+ const rootContext = createRootContext();
1339
+ const rootTask = createTask(request, model, rootContext, abortSet);
1241
1340
  pingedTasks.push(rootTask);
1242
1341
  return request;
1243
1342
  }
@@ -1248,9 +1347,13 @@ function resolveRequest() {
1248
1347
  return null;
1249
1348
  }
1250
1349
 
1251
- function serializeThenable(request, task, thenable) {
1252
- const newTask = createTask(request, null, task.keyPath, // the server component sequence continues through Promise-as-a-child.
1253
- task.implicitSlot, request.abortableTasks);
1350
+ function createRootContext(reqContext) {
1351
+ return importServerContexts();
1352
+ }
1353
+
1354
+ function serializeThenable(request, thenable) {
1355
+ request.pendingChunks++;
1356
+ const newTask = createTask(request, null, getActiveContext(), request.abortableTasks);
1254
1357
 
1255
1358
  switch (thenable.status) {
1256
1359
  case 'fulfilled':
@@ -1384,117 +1487,61 @@ function createLazyWrapperAroundWakeable(wakeable) {
1384
1487
  _payload: thenable,
1385
1488
  _init: readThenable
1386
1489
  };
1387
-
1388
1490
  return lazyType;
1389
1491
  }
1390
1492
 
1391
- function renderFunctionComponent(request, task, key, Component, props) {
1392
- // Reset the task's thenable state before continuing, so that if a later
1393
- // component suspends we can reuse the same task object. If the same
1394
- // component suspends again, the thenable state will be restored.
1395
- const prevThenableState = task.thenableState;
1396
- task.thenableState = null;
1397
-
1398
- prepareToUseHooksForComponent(prevThenableState); // The secondArg is always undefined in Server Components since refs error early.
1399
-
1400
- const secondArg = undefined;
1401
- let result = Component(props, secondArg);
1402
-
1403
- if (typeof result === 'object' && result !== null && typeof result.then === 'function') {
1404
- // When the return value is in children position we can resolve it immediately,
1405
- // to its value without a wrapper if it's synchronously available.
1406
- const thenable = result;
1407
-
1408
- if (thenable.status === 'fulfilled') {
1409
- return thenable.value;
1410
- } // TODO: Once we accept Promises as children on the client, we can just return
1411
- // the thenable here.
1412
-
1413
-
1414
- result = createLazyWrapperAroundWakeable(result);
1415
- } // Track this element's key on the Server Component on the keyPath context..
1416
-
1417
-
1418
- const prevKeyPath = task.keyPath;
1419
- const prevImplicitSlot = task.implicitSlot;
1420
-
1421
- if (key !== null) {
1422
- // Append the key to the path. Technically a null key should really add the child
1423
- // index. We don't do that to hold the payload small and implementation simple.
1424
- task.keyPath = prevKeyPath === null ? key : prevKeyPath + ',' + key;
1425
- } else if (prevKeyPath === null) {
1426
- // This sequence of Server Components has no keys. This means that it was rendered
1427
- // in a slot that needs to assign an implicit key. Even if children below have
1428
- // explicit keys, they should not be used for the outer most key since it might
1429
- // collide with other slots in that set.
1430
- task.implicitSlot = true;
1431
- }
1432
-
1433
- const json = renderModelDestructive(request, task, emptyRoot, '', result);
1434
- task.keyPath = prevKeyPath;
1435
- task.implicitSlot = prevImplicitSlot;
1436
- return json;
1437
- }
1438
-
1439
- function renderFragment(request, task, children) {
1440
-
1441
- {
1442
- return children;
1443
- }
1444
- }
1445
-
1446
- function renderClientElement(task, type, key, props) {
1447
- {
1448
- return [REACT_ELEMENT_TYPE, type, key, props];
1449
- } // We prepend the terminal client element that actually gets serialized with
1450
- } // The chunk ID we're currently rendering that we can assign debug data to.
1451
-
1452
-
1453
- let debugID = null;
1454
-
1455
- function renderElement(request, task, type, key, ref, props) {
1493
+ function attemptResolveElement(request, type, key, ref, props, prevThenableState) {
1456
1494
  if (ref !== null && ref !== undefined) {
1457
1495
  // When the ref moves to the regular props object this will implicitly
1458
1496
  // throw for functions. We could probably relax it to a DEV warning for other
1459
1497
  // cases.
1460
- // TODO: `ref` is now just a prop when `enableRefAsProp` is on. Should we
1461
- // do what the above comment says?
1462
1498
  throw new Error('Refs cannot be used in Server Components, nor passed to Client Components.');
1463
1499
  }
1464
1500
 
1465
1501
  if (typeof type === 'function') {
1466
1502
  if (isClientReference(type)) {
1467
1503
  // This is a reference to a Client Component.
1468
- return renderClientElement(task, type, key, props);
1469
- } // This is a Server Component.
1504
+ return [REACT_ELEMENT_TYPE, type, key, props];
1505
+ } // This is a server-side component.
1506
+
1507
+
1508
+ prepareToUseHooksForComponent(prevThenableState);
1509
+ const result = type(props);
1510
+
1511
+ if (typeof result === 'object' && result !== null && typeof result.then === 'function') {
1512
+ // When the return value is in children position we can resolve it immediately,
1513
+ // to its value without a wrapper if it's synchronously available.
1514
+ const thenable = result;
1470
1515
 
1516
+ if (thenable.status === 'fulfilled') {
1517
+ return thenable.value;
1518
+ } // TODO: Once we accept Promises as children on the client, we can just return
1519
+ // the thenable here.
1471
1520
 
1472
- return renderFunctionComponent(request, task, key, type, props);
1521
+
1522
+ return createLazyWrapperAroundWakeable(result);
1523
+ }
1524
+
1525
+ return result;
1473
1526
  } else if (typeof type === 'string') {
1474
1527
  // This is a host element. E.g. HTML.
1475
- return renderClientElement(task, type, key, props);
1528
+ return [REACT_ELEMENT_TYPE, type, key, props];
1476
1529
  } else if (typeof type === 'symbol') {
1477
- if (type === REACT_FRAGMENT_TYPE && key === null) {
1530
+ if (type === REACT_FRAGMENT_TYPE) {
1478
1531
  // For key-less fragments, we add a small optimization to avoid serializing
1479
1532
  // it as a wrapper.
1480
- const prevImplicitSlot = task.implicitSlot;
1481
-
1482
- if (task.keyPath === null) {
1483
- task.implicitSlot = true;
1484
- }
1485
-
1486
- const json = renderModelDestructive(request, task, emptyRoot, '', props.children);
1487
- task.implicitSlot = prevImplicitSlot;
1488
- return json;
1533
+ // TODO: If a key is specified, we should propagate its key to any children.
1534
+ // Same as if a Server Component has a key.
1535
+ return props.children;
1489
1536
  } // This might be a built-in React component. We'll let the client decide.
1490
1537
  // Any built-in works as long as its props are serializable.
1491
1538
 
1492
1539
 
1493
- return renderClientElement(task, type, key, props);
1540
+ return [REACT_ELEMENT_TYPE, type, key, props];
1494
1541
  } else if (type != null && typeof type === 'object') {
1495
1542
  if (isClientReference(type)) {
1496
1543
  // This is a reference to a Client Component.
1497
- return renderClientElement(task, type, key, props);
1544
+ return [REACT_ELEMENT_TYPE, type, key, props];
1498
1545
  }
1499
1546
 
1500
1547
  switch (type.$$typeof) {
@@ -1503,17 +1550,19 @@ function renderElement(request, task, type, key, ref, props) {
1503
1550
  const payload = type._payload;
1504
1551
  const init = type._init;
1505
1552
  const wrappedType = init(payload);
1506
- return renderElement(request, task, wrappedType, key, ref, props);
1553
+ return attemptResolveElement(request, wrappedType, key, ref, props, prevThenableState);
1507
1554
  }
1508
1555
 
1509
1556
  case REACT_FORWARD_REF_TYPE:
1510
1557
  {
1511
- return renderFunctionComponent(request, task, key, type.render, props);
1558
+ const render = type.render;
1559
+ prepareToUseHooksForComponent(prevThenableState);
1560
+ return render(props, undefined);
1512
1561
  }
1513
1562
 
1514
1563
  case REACT_MEMO_TYPE:
1515
1564
  {
1516
- return renderElement(request, task, type.type, key, ref, props);
1565
+ return attemptResolveElement(request, type.type, key, ref, props, prevThenableState);
1517
1566
  }
1518
1567
  }
1519
1568
  }
@@ -1531,30 +1580,14 @@ function pingTask(request, task) {
1531
1580
  }
1532
1581
  }
1533
1582
 
1534
- function createTask(request, model, keyPath, implicitSlot, abortSet) {
1535
- request.pendingChunks++;
1583
+ function createTask(request, model, context, abortSet) {
1536
1584
  const id = request.nextChunkId++;
1537
-
1538
- if (typeof model === 'object' && model !== null) {
1539
- // If we're about to write this into a new task we can assign it an ID early so that
1540
- // any other references can refer to the value we're about to write.
1541
- {
1542
- request.writtenObjects.set(model, id);
1543
- }
1544
- }
1545
-
1546
1585
  const task = {
1547
1586
  id,
1548
1587
  status: PENDING$1,
1549
1588
  model,
1550
- keyPath,
1551
- implicitSlot,
1589
+ context,
1552
1590
  ping: () => pingTask(request, task),
1553
- toJSON: function (parentPropertyName, value) {
1554
- const parent = this; // Make sure that `parent[parentPropertyName]` wasn't JSONified before `value` was passed to us
1555
-
1556
- return renderModel(request, task, parent, parentPropertyName, value);
1557
- },
1558
1591
  thenableState: null
1559
1592
  };
1560
1593
  abortSet.add(task);
@@ -1623,13 +1656,13 @@ function encodeReferenceChunk(request, id, reference) {
1623
1656
  return stringToChunk(row);
1624
1657
  }
1625
1658
 
1626
- function serializeClientReference(request, parent, parentPropertyName, clientReference) {
1659
+ function serializeClientReference(request, parent, key, clientReference) {
1627
1660
  const clientReferenceKey = getClientReferenceKey(clientReference);
1628
1661
  const writtenClientReferences = request.writtenClientReferences;
1629
1662
  const existingId = writtenClientReferences.get(clientReferenceKey);
1630
1663
 
1631
1664
  if (existingId !== undefined) {
1632
- if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {
1665
+ if (parent[0] === REACT_ELEMENT_TYPE && key === '1') {
1633
1666
  // If we're encoding the "type" of an element, we can refer
1634
1667
  // to that by a lazy reference instead of directly since React
1635
1668
  // knows how to deal with lazy values. This lets us suspend
@@ -1648,7 +1681,7 @@ function serializeClientReference(request, parent, parentPropertyName, clientRef
1648
1681
  emitImportChunk(request, importId, clientReferenceMetadata);
1649
1682
  writtenClientReferences.set(clientReferenceKey, importId);
1650
1683
 
1651
- if (parent[0] === REACT_ELEMENT_TYPE && parentPropertyName === '1') {
1684
+ if (parent[0] === REACT_ELEMENT_TYPE && key === '1') {
1652
1685
  // If we're encoding the "type" of an element, we can refer
1653
1686
  // to that by a lazy reference instead of directly since React
1654
1687
  // knows how to deal with lazy values. This lets us suspend
@@ -1668,14 +1701,13 @@ function serializeClientReference(request, parent, parentPropertyName, clientRef
1668
1701
  }
1669
1702
 
1670
1703
  function outlineModel(request, value) {
1671
- const newTask = createTask(request, value, null, // The way we use outlining is for reusing an object.
1672
- false, // It makes no sense for that use case to be contextual.
1673
- request.abortableTasks);
1704
+ request.pendingChunks++;
1705
+ const newTask = createTask(request, value, getActiveContext(), request.abortableTasks);
1674
1706
  retryTask(request, newTask);
1675
1707
  return newTask.id;
1676
1708
  }
1677
1709
 
1678
- function serializeServerReference(request, serverReference) {
1710
+ function serializeServerReference(request, parent, key, serverReference) {
1679
1711
  const writtenServerReferences = request.writtenServerReferences;
1680
1712
  const existingId = writtenServerReferences.get(serverReference);
1681
1713
 
@@ -1755,77 +1787,91 @@ function escapeStringValue(value) {
1755
1787
  return value;
1756
1788
  }
1757
1789
  }
1758
-
1759
1790
  let modelRoot = false;
1760
1791
 
1761
- function renderModel(request, task, parent, key, value) {
1762
- const prevKeyPath = task.keyPath;
1763
- const prevImplicitSlot = task.implicitSlot;
1792
+ function resolveModelToJSON(request, parent, key, value) {
1764
1793
 
1765
- try {
1766
- return renderModelDestructive(request, task, parent, key, value);
1767
- } catch (thrownValue) {
1768
- const x = thrownValue === SuspenseException ? // This is a special type of exception used for Suspense. For historical
1769
- // reasons, the rest of the Suspense implementation expects the thrown
1770
- // value to be a thenable, because before `use` existed that was the
1771
- // (unstable) API for suspending. This implementation detail can change
1772
- // later, once we deprecate the old API in favor of `use`.
1773
- getSuspendedThenable() : thrownValue; // If the suspended/errored value was an element or lazy it can be reduced
1774
- // to a lazy reference, so that it doesn't error the parent.
1775
1794
 
1776
- const model = task.model;
1777
- const wasReactNode = typeof model === 'object' && model !== null && (model.$$typeof === REACT_ELEMENT_TYPE || model.$$typeof === REACT_LAZY_TYPE);
1795
+ switch (value) {
1796
+ case REACT_ELEMENT_TYPE:
1797
+ return '$';
1798
+ }
1778
1799
 
1779
- if (typeof x === 'object' && x !== null) {
1780
- // $FlowFixMe[method-unbinding]
1781
- if (typeof x.then === 'function') {
1782
- // Something suspended, we'll need to create a new task and resolve it later.
1783
- const newTask = createTask(request, task.model, task.keyPath, task.implicitSlot, request.abortableTasks);
1784
- const ping = newTask.ping;
1785
- x.then(ping, ping);
1786
- newTask.thenableState = getThenableStateAfterSuspending(); // Restore the context. We assume that this will be restored by the inner
1787
- // functions in case nothing throws so we don't use "finally" here.
1788
1800
 
1789
- task.keyPath = prevKeyPath;
1790
- task.implicitSlot = prevImplicitSlot;
1801
+ while (typeof value === 'object' && value !== null && (value.$$typeof === REACT_ELEMENT_TYPE || value.$$typeof === REACT_LAZY_TYPE)) {
1791
1802
 
1792
- if (wasReactNode) {
1793
- return serializeLazyID(newTask.id);
1794
- }
1803
+ try {
1804
+ switch (value.$$typeof) {
1805
+ case REACT_ELEMENT_TYPE:
1806
+ {
1807
+ const writtenObjects = request.writtenObjects;
1808
+ const existingId = writtenObjects.get(value);
1809
+
1810
+ if (existingId !== undefined) {
1811
+ if (existingId === -1) {
1812
+ // Seen but not yet outlined.
1813
+ const newId = outlineModel(request, value);
1814
+ return serializeByValueID(newId);
1815
+ } else if (modelRoot === value) {
1816
+ // This is the ID we're currently emitting so we need to write it
1817
+ // once but if we discover it again, we refer to it by id.
1818
+ modelRoot = null;
1819
+ } else {
1820
+ // We've already emitted this as an outlined object, so we can
1821
+ // just refer to that by its existing ID.
1822
+ return serializeByValueID(existingId);
1823
+ }
1824
+ } else {
1825
+ // This is the first time we've seen this object. We may never see it again
1826
+ // so we'll inline it. Mark it as seen. If we see it again, we'll outline.
1827
+ writtenObjects.set(value, -1);
1828
+ } // TODO: Concatenate keys of parents onto children.
1795
1829
 
1796
- return serializeByValueID(newTask.id);
1797
- }
1798
- } // Restore the context. We assume that this will be restored by the inner
1799
- // functions in case nothing throws so we don't use "finally" here.
1800
1830
 
1831
+ const element = value; // Attempt to render the Server Component.
1801
1832
 
1802
- task.keyPath = prevKeyPath;
1803
- task.implicitSlot = prevImplicitSlot;
1833
+ value = attemptResolveElement(request, element.type, element.key, element.ref, element.props, null);
1834
+ break;
1835
+ }
1804
1836
 
1805
- if (wasReactNode) {
1806
- // Something errored. We'll still send everything we have up until this point.
1837
+ case REACT_LAZY_TYPE:
1838
+ {
1839
+ const payload = value._payload;
1840
+ const init = value._init;
1841
+ value = init(payload);
1842
+ break;
1843
+ }
1844
+ }
1845
+ } catch (thrownValue) {
1846
+ const x = thrownValue === SuspenseException ? // This is a special type of exception used for Suspense. For historical
1847
+ // reasons, the rest of the Suspense implementation expects the thrown
1848
+ // value to be a thenable, because before `use` existed that was the
1849
+ // (unstable) API for suspending. This implementation detail can change
1850
+ // later, once we deprecate the old API in favor of `use`.
1851
+ getSuspendedThenable() : thrownValue;
1852
+
1853
+ if (typeof x === 'object' && x !== null) {
1854
+ // $FlowFixMe[method-unbinding]
1855
+ if (typeof x.then === 'function') {
1856
+ // Something suspended, we'll need to create a new task and resolve it later.
1857
+ request.pendingChunks++;
1858
+ const newTask = createTask(request, value, getActiveContext(), request.abortableTasks);
1859
+ const ping = newTask.ping;
1860
+ x.then(ping, ping);
1861
+ newTask.thenableState = getThenableStateAfterSuspending();
1862
+ return serializeLazyID(newTask.id);
1863
+ }
1864
+ } // Something errored. We'll still send everything we have up until this point.
1807
1865
  // We'll replace this element with a lazy reference that throws on the client
1808
1866
  // once it gets rendered.
1867
+
1868
+
1809
1869
  request.pendingChunks++;
1810
1870
  const errorId = request.nextChunkId++;
1811
1871
  const digest = logRecoverableError(request, x);
1812
1872
  emitErrorChunk(request, errorId, digest);
1813
1873
  return serializeLazyID(errorId);
1814
- } // Something errored but it was not in a React Node. There's no need to serialize
1815
- // it by value because it'll just error the whole parent row anyway so we can
1816
- // just stop any siblings and error the whole parent row.
1817
-
1818
-
1819
- throw x;
1820
- }
1821
- }
1822
-
1823
- function renderModelDestructive(request, task, parent, parentPropertyName, value) {
1824
- // Set the currently rendering model
1825
- task.model = value; // Special Symbol, that's very common.
1826
-
1827
- if (value === REACT_ELEMENT_TYPE) {
1828
- return '$';
1874
+ }
1829
1875
  }
1830
1876
 
1831
1877
  if (value === null) {
@@ -1833,70 +1879,9 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1833
1879
  }
1834
1880
 
1835
1881
  if (typeof value === 'object') {
1836
- switch (value.$$typeof) {
1837
- case REACT_ELEMENT_TYPE:
1838
- {
1839
- const writtenObjects = request.writtenObjects;
1840
- const existingId = writtenObjects.get(value);
1841
-
1842
- if (existingId !== undefined) {
1843
- if (modelRoot === value) {
1844
- // This is the ID we're currently emitting so we need to write it
1845
- // once but if we discover it again, we refer to it by id.
1846
- modelRoot = null;
1847
- } else if (existingId === -1) {
1848
- // Seen but not yet outlined.
1849
- // TODO: If we throw here we can treat this as suspending which causes an outline
1850
- // but that is able to reuse the same task if we're already in one but then that
1851
- // will be a lazy future value rather than guaranteed to exist but maybe that's good.
1852
- const newId = outlineModel(request, value);
1853
- return serializeByValueID(newId);
1854
- } else {
1855
- // We've already emitted this as an outlined object, so we can refer to that by its
1856
- // existing ID. TODO: We should use a lazy reference since, unlike plain objects,
1857
- // elements might suspend so it might not have emitted yet even if we have the ID for
1858
- // it. However, this creates an extra wrapper when it's not needed. We should really
1859
- // detect whether this already was emitted and synchronously available. In that
1860
- // case we can refer to it synchronously and only make it lazy otherwise.
1861
- // We currently don't have a data structure that lets us see that though.
1862
- return serializeByValueID(existingId);
1863
- }
1864
- } else {
1865
- // This is the first time we've seen this object. We may never see it again
1866
- // so we'll inline it. Mark it as seen. If we see it again, we'll outline.
1867
- writtenObjects.set(value, -1);
1868
- }
1869
-
1870
- const element = value;
1871
-
1872
- const props = element.props;
1873
- let ref;
1874
-
1875
- {
1876
- ref = element.ref;
1877
- } // Attempt to render the Server Component.
1878
-
1879
-
1880
- return renderElement(request, task, element.type, // $FlowFixMe[incompatible-call] the key of an element is null | string
1881
- element.key, ref, props);
1882
- }
1883
-
1884
- case REACT_LAZY_TYPE:
1885
- {
1886
- // Reset the task's thenable state before continuing. If there was one, it was
1887
- // from suspending the lazy before.
1888
- task.thenableState = null;
1889
- const lazy = value;
1890
- const payload = lazy._payload;
1891
- const init = lazy._init;
1892
- const resolvedModel = init(payload);
1893
-
1894
- return renderModelDestructive(request, task, emptyRoot, '', resolvedModel);
1895
- }
1896
- }
1897
1882
 
1898
1883
  if (isClientReference(value)) {
1899
- return serializeClientReference(request, parent, parentPropertyName, value);
1884
+ return serializeClientReference(request, parent, key, value);
1900
1885
  }
1901
1886
 
1902
1887
  const writtenObjects = request.writtenObjects;
@@ -1916,20 +1901,20 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1916
1901
  // or a Promise type. Either of which can be represented by a Promise.
1917
1902
 
1918
1903
 
1919
- const promiseId = serializeThenable(request, task, value);
1904
+ const promiseId = serializeThenable(request, value);
1920
1905
  writtenObjects.set(value, promiseId);
1921
1906
  return serializePromiseID(promiseId);
1922
1907
  }
1923
1908
 
1924
1909
  if (existingId !== undefined) {
1925
- if (modelRoot === value) {
1926
- // This is the ID we're currently emitting so we need to write it
1927
- // once but if we discover it again, we refer to it by id.
1928
- modelRoot = null;
1929
- } else if (existingId === -1) {
1910
+ if (existingId === -1) {
1930
1911
  // Seen but not yet outlined.
1931
1912
  const newId = outlineModel(request, value);
1932
1913
  return serializeByValueID(newId);
1914
+ } else if (modelRoot === value) {
1915
+ // This is the ID we're currently emitting so we need to write it
1916
+ // once but if we discover it again, we refer to it by id.
1917
+ modelRoot = null;
1933
1918
  } else {
1934
1919
  // We've already emitted this as an outlined object, so we can
1935
1920
  // just refer to that by its existing ID.
@@ -1942,7 +1927,8 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1942
1927
  }
1943
1928
 
1944
1929
  if (isArray(value)) {
1945
- return renderFragment(request, task, value);
1930
+ // $FlowFixMe[incompatible-return]
1931
+ return value;
1946
1932
  }
1947
1933
 
1948
1934
  if (value instanceof Map) {
@@ -1956,7 +1942,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1956
1942
  const iteratorFn = getIteratorFn(value);
1957
1943
 
1958
1944
  if (iteratorFn) {
1959
- return renderFragment(request, task, Array.from(value));
1945
+ return Array.from(value);
1960
1946
  } // Verify that this is a simple plain object.
1961
1947
 
1962
1948
 
@@ -1976,7 +1962,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
1976
1962
  if (value[value.length - 1] === 'Z') {
1977
1963
  // Possibly a Date, whose toJSON automatically calls toISOString
1978
1964
  // $FlowFixMe[incompatible-use]
1979
- const originalValue = parent[parentPropertyName];
1965
+ const originalValue = parent[key];
1980
1966
 
1981
1967
  if (originalValue instanceof Date) {
1982
1968
  return serializeDateFromDateJSON(value);
@@ -2006,18 +1992,19 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2006
1992
  }
2007
1993
 
2008
1994
  if (typeof value === 'function') {
1995
+
2009
1996
  if (isClientReference(value)) {
2010
- return serializeClientReference(request, parent, parentPropertyName, value);
1997
+ return serializeClientReference(request, parent, key, value);
2011
1998
  }
2012
1999
 
2013
2000
  if (isServerReference(value)) {
2014
- return serializeServerReference(request, value);
2001
+ return serializeServerReference(request, parent, key, value);
2015
2002
  }
2016
2003
 
2017
- if (/^on[A-Z]/.test(parentPropertyName)) {
2018
- throw new Error('Event handlers cannot be passed to Client Component props.' + describeObjectForErrorMessage(parent, parentPropertyName) + '\nIf you need interactivity, consider converting part of this to a Client Component.');
2004
+ if (/^on[A-Z]/.test(key)) {
2005
+ throw new Error('Event handlers cannot be passed to Client Component props.' + describeObjectForErrorMessage(parent, key) + '\nIf you need interactivity, consider converting part of this to a Client Component.');
2019
2006
  } else {
2020
- throw new Error('Functions cannot be passed directly to Client Components ' + 'unless you explicitly expose it by marking it with "use server". ' + 'Or maybe you meant to call this function rather than return it.' + describeObjectForErrorMessage(parent, parentPropertyName));
2007
+ throw new Error('Functions cannot be passed directly to Client Components ' + 'unless you explicitly expose it by marking it with "use server".' + describeObjectForErrorMessage(parent, key));
2021
2008
  }
2022
2009
  }
2023
2010
 
@@ -2034,7 +2021,7 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2034
2021
 
2035
2022
  if (Symbol.for(name) !== value) {
2036
2023
  throw new Error('Only global symbols received from Symbol.for(...) can be passed to Client Components. ' + ("The symbol Symbol.for(" + // $FlowFixMe[incompatible-type] `description` might be undefined
2037
- value.description + ") cannot be found among global symbols.") + describeObjectForErrorMessage(parent, parentPropertyName));
2024
+ value.description + ") cannot be found among global symbols.") + describeObjectForErrorMessage(parent, key));
2038
2025
  }
2039
2026
 
2040
2027
  request.pendingChunks++;
@@ -2049,38 +2036,17 @@ function renderModelDestructive(request, task, parent, parentPropertyName, value
2049
2036
  return serializeBigInt(value);
2050
2037
  }
2051
2038
 
2052
- throw new Error("Type " + typeof value + " is not supported in Client Component props." + describeObjectForErrorMessage(parent, parentPropertyName));
2039
+ throw new Error("Type " + typeof value + " is not supported in Client Component props." + describeObjectForErrorMessage(parent, key));
2053
2040
  }
2054
2041
 
2055
2042
  function logPostpone(request, reason) {
2056
- const prevRequest = currentRequest;
2057
- currentRequest = null;
2058
-
2059
- try {
2060
- const onPostpone = request.onPostpone;
2061
-
2062
- if (supportsRequestStorage) ; else {
2063
- onPostpone(reason);
2064
- }
2065
- } finally {
2066
- currentRequest = prevRequest;
2067
- }
2043
+ const onPostpone = request.onPostpone;
2044
+ onPostpone(reason);
2068
2045
  }
2069
2046
 
2070
2047
  function logRecoverableError(request, error) {
2071
- const prevRequest = currentRequest;
2072
- currentRequest = null;
2073
- let errorDigest;
2074
-
2075
- try {
2076
- const onError = request.onError;
2077
-
2078
- if (supportsRequestStorage) ; else {
2079
- errorDigest = onError(error);
2080
- }
2081
- } finally {
2082
- currentRequest = prevRequest;
2083
- }
2048
+ const onError = request.onError;
2049
+ const errorDigest = onError(error);
2084
2050
 
2085
2051
  if (errorDigest != null && typeof errorDigest !== 'string') {
2086
2052
  // eslint-disable-next-line react-internal/prod-error-codes
@@ -2150,54 +2116,62 @@ function emitSymbolChunk(request, id, name) {
2150
2116
  request.completedImportChunks.push(processedChunk);
2151
2117
  }
2152
2118
 
2153
- function emitModelChunk(request, id, json) {
2119
+ function emitModelChunk(request, id, model) {
2120
+ // Track the root so we know that we have to emit this object even though it
2121
+ // already has an ID. This is needed because we might see this object twice
2122
+ // in the same toJSON if it is cyclic.
2123
+ modelRoot = model; // $FlowFixMe[incompatible-type] stringify can return null
2124
+
2125
+ const json = stringify(model, request.toJSON);
2154
2126
  const row = id.toString(16) + ':' + json + '\n';
2155
2127
  const processedChunk = stringToChunk(row);
2156
2128
  request.completedRegularChunks.push(processedChunk);
2157
2129
  }
2158
2130
 
2159
- const emptyRoot = {};
2160
-
2161
2131
  function retryTask(request, task) {
2162
2132
  if (task.status !== PENDING$1) {
2163
2133
  // We completed this by other means before we had a chance to retry it.
2164
2134
  return;
2165
2135
  }
2166
2136
 
2137
+ switchContext(task.context);
2138
+
2167
2139
  try {
2168
- // Track the root so we know that we have to emit this object even though it
2169
- // already has an ID. This is needed because we might see this object twice
2170
- // in the same toJSON if it is cyclic.
2171
- modelRoot = task.model;
2140
+ let value = task.model;
2172
2141
 
2173
- if (false) ; // We call the destructive form that mutates this task. That way if something
2174
- // suspends again, we can reuse the same task instead of spawning a new one.
2142
+ if (typeof value === 'object' && value !== null && value.$$typeof === REACT_ELEMENT_TYPE) {
2143
+ request.writtenObjects.set(value, task.id); // TODO: Concatenate keys of parents onto children.
2175
2144
 
2145
+ const element = value; // When retrying a component, reuse the thenableState from the
2146
+ // previous attempt.
2176
2147
 
2177
- const resolvedModel = renderModelDestructive(request, task, emptyRoot, '', task.model);
2148
+ const prevThenableState = task.thenableState; // Attempt to render the Server Component.
2149
+ // Doing this here lets us reuse this same task if the next component
2150
+ // also suspends.
2178
2151
 
2179
- if (false) ; // Track the root again for the resolved object.
2152
+ task.model = value;
2153
+ value = attemptResolveElement(request, element.type, element.key, element.ref, element.props, prevThenableState); // Successfully finished this component. We're going to keep rendering
2154
+ // using the same task, but we reset its thenable state before continuing.
2180
2155
 
2156
+ task.thenableState = null; // Keep rendering and reuse the same task. This inner loop is separate
2157
+ // from the render above because we don't need to reset the thenable state
2158
+ // until the next time something suspends and retries.
2181
2159
 
2182
- modelRoot = resolvedModel; // The keyPath resets at any terminal child node.
2160
+ while (typeof value === 'object' && value !== null && value.$$typeof === REACT_ELEMENT_TYPE) {
2161
+ request.writtenObjects.set(value, task.id); // TODO: Concatenate keys of parents onto children.
2183
2162
 
2184
- task.keyPath = null;
2185
- task.implicitSlot = false;
2186
- let json;
2163
+ const nextElement = value;
2164
+ task.model = value;
2165
+ value = attemptResolveElement(request, nextElement.type, nextElement.key, nextElement.ref, nextElement.props, null);
2166
+ }
2167
+ } // Track that this object is outlined and has an id.
2187
2168
 
2188
- if (typeof resolvedModel === 'object' && resolvedModel !== null) {
2189
- // Object might contain unresolved values like additional elements.
2190
- // This is simulating what the JSON loop would do if this was part of it.
2191
- // $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do
2192
- json = stringify(resolvedModel, task.toJSON);
2193
- } else {
2194
- // If the value is a string, it means it's a terminal value and we already escaped it
2195
- // We don't need to escape it again so it's not passed the toJSON replacer.
2196
- // $FlowFixMe[incompatible-type] stringify can return null for undefined but we never do
2197
- json = stringify(resolvedModel);
2169
+
2170
+ if (typeof value === 'object' && value !== null) {
2171
+ request.writtenObjects.set(value, task.id);
2198
2172
  }
2199
2173
 
2200
- emitModelChunk(request, task.id, json);
2174
+ emitModelChunk(request, task.id, value);
2201
2175
  request.abortableTasks.delete(task);
2202
2176
  task.status = COMPLETED;
2203
2177
  } catch (thrownValue) {
@@ -2223,7 +2197,6 @@ function retryTask(request, task) {
2223
2197
  task.status = ERRORED$1;
2224
2198
  const digest = logRecoverableError(request, x);
2225
2199
  emitErrorChunk(request, task.id, digest);
2226
- } finally {
2227
2200
  }
2228
2201
  }
2229
2202
 
@@ -2411,6 +2384,11 @@ function abort(request, reason) {
2411
2384
  }
2412
2385
  }
2413
2386
 
2387
+ function importServerContexts(contexts) {
2388
+
2389
+ return rootContextSnapshot;
2390
+ }
2391
+
2414
2392
  // This is the parsed shape of the wire format which is why it is
2415
2393
  // condensed to only the essentialy information
2416
2394
  const ID = 0;
@@ -3116,7 +3094,7 @@ function decodeFormState(actionResult, body, serverManifest) {
3116
3094
  }
3117
3095
 
3118
3096
  function renderToReadableStream(model, webpackMap, options) {
3119
- const request = createRequest(model, webpackMap, options ? options.onError : undefined, options ? options.identifierPrefix : undefined, options ? options.onPostpone : undefined);
3097
+ const request = createRequest(model, webpackMap, options ? options.onError : undefined, options ? options.context : undefined, options ? options.identifierPrefix : undefined, options ? options.onPostpone : undefined);
3120
3098
 
3121
3099
  if (options && options.signal) {
3122
3100
  const signal = options.signal;