Skip to content

Commit 20e0d8b

Browse files
committed
Move formatContext tracking back to the task
This is really conceptually two different values. Task is keeping track of the working state of the currently executing context. The segment just needs to keep track of which parent context it was created in so that it can be wrapped correctly when a segment is written. We just happened to rely on the working state returning to the top before completing.
1 parent 7022e8d commit 20e0d8b

File tree

1 file changed

+23
-17
lines changed

1 file changed

+23
-17
lines changed

packages/react-server/src/ReactFizzServer.js

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ export type Task = {
221221
blockedSegment: Segment, // the segment we'll write to
222222
abortSet: Set<Task>, // the abortable set that this task belongs to
223223
keyPath: Root | KeyNode, // the path of all parent keys currently rendering
224+
formatContext: FormatContext, // the format's specific context (e.g. HTML/SVG/MathML)
224225
legacyContext: LegacyContext, // the current legacy context that this task is executing in
225226
context: ContextSnapshot, // the current new context that this task is executing in
226227
treeContext: TreeContext, // the current tree context that this task is executing in
@@ -245,7 +246,7 @@ type Segment = {
245246
+chunks: Array<Chunk | PrecomputedChunk>,
246247
+children: Array<Segment>,
247248
// The context that this segment was created in.
248-
formatContext: FormatContext,
249+
parentFormatContext: FormatContext,
249250
// If this segment represents a fallback, this is the content that will replace that fallback.
250251
+boundary: null | SuspenseBoundary,
251252
// used to discern when text separator boundaries are needed
@@ -386,6 +387,7 @@ export function createRequest(
386387
rootSegment,
387388
abortSet,
388389
null,
390+
rootFormatContext,
389391
emptyContextObject,
390392
rootContextSnapshot,
391393
emptyTreeContext,
@@ -442,6 +444,7 @@ function createTask(
442444
blockedSegment: Segment,
443445
abortSet: Set<Task>,
444446
keyPath: Root | KeyNode,
447+
formatContext: FormatContext,
445448
legacyContext: LegacyContext,
446449
context: ContextSnapshot,
447450
treeContext: TreeContext,
@@ -459,6 +462,7 @@ function createTask(
459462
blockedSegment,
460463
abortSet,
461464
keyPath,
465+
formatContext,
462466
legacyContext,
463467
context,
464468
treeContext,
@@ -475,7 +479,7 @@ function createPendingSegment(
475479
request: Request,
476480
index: number,
477481
boundary: null | SuspenseBoundary,
478-
formatContext: FormatContext,
482+
parentFormatContext: FormatContext,
479483
lastPushedText: boolean,
480484
textEmbedded: boolean,
481485
): Segment {
@@ -486,7 +490,7 @@ function createPendingSegment(
486490
parentFlushed: false,
487491
chunks: [],
488492
children: [],
489-
formatContext,
493+
parentFormatContext,
490494
boundary,
491495
lastPushedText,
492496
textEmbedded,
@@ -635,7 +639,7 @@ function renderSuspenseBoundary(
635639
request,
636640
insertionIndex,
637641
newBoundary,
638-
parentSegment.formatContext,
642+
task.formatContext,
639643
// boundaries never require text embedding at their edges because comment nodes bound them
640644
false,
641645
false,
@@ -649,7 +653,7 @@ function renderSuspenseBoundary(
649653
request,
650654
0,
651655
null,
652-
parentSegment.formatContext,
656+
task.formatContext,
653657
// boundaries never require text embedding at their edges because comment nodes bound them
654658
false,
655659
false,
@@ -739,6 +743,7 @@ function renderSuspenseBoundary(
739743
boundarySegment,
740744
fallbackAbortSet,
741745
task.keyPath,
746+
task.formatContext,
742747
task.legacyContext,
743748
task.context,
744749
task.treeContext,
@@ -785,20 +790,20 @@ function renderHostElement(
785790
props,
786791
request.resumableState,
787792
request.renderState,
788-
segment.formatContext,
793+
task.formatContext,
789794
segment.lastPushedText,
790795
);
791796
segment.lastPushedText = false;
792-
const prevContext = segment.formatContext;
793-
segment.formatContext = getChildFormatContext(prevContext, type, props);
797+
const prevContext = task.formatContext;
798+
task.formatContext = getChildFormatContext(prevContext, type, props);
794799

795800
// We use the non-destructive form because if something suspends, we still
796801
// need to pop back up and finish this subtree of HTML.
797802
renderNode(request, task, children, 0);
798803

799804
// We expect that errors will fatal the whole task and that we don't need
800805
// the correct context. Therefore this is not in a finally.
801-
segment.formatContext = prevContext;
806+
task.formatContext = prevContext;
802807
pushEndInstance(
803808
segment.chunks,
804809
type,
@@ -1740,7 +1745,7 @@ function injectPostponedHole(
17401745
request,
17411746
insertionIndex,
17421747
null,
1743-
segment.formatContext,
1748+
task.formatContext,
17441749
// Adopt the parent segment's leading text embed
17451750
segment.lastPushedText,
17461751
// Assume we are text embedded at the trailing edge
@@ -1765,7 +1770,7 @@ function spawnNewSuspendedTask(
17651770
request,
17661771
insertionIndex,
17671772
null,
1768-
segment.formatContext,
1773+
task.formatContext,
17691774
// Adopt the parent segment's leading text embed
17701775
segment.lastPushedText,
17711776
// Assume we are text embedded at the trailing edge
@@ -1782,6 +1787,7 @@ function spawnNewSuspendedTask(
17821787
newSegment,
17831788
task.abortSet,
17841789
task.keyPath,
1790+
task.formatContext,
17851791
task.legacyContext,
17861792
task.context,
17871793
task.treeContext,
@@ -1814,7 +1820,7 @@ function renderNode(
18141820

18151821
// Snapshot the current context in case something throws to interrupt the
18161822
// process.
1817-
const previousFormatContext = task.blockedSegment.formatContext;
1823+
const previousFormatContext = task.formatContext;
18181824
const previousLegacyContext = task.legacyContext;
18191825
const previousContext = task.context;
18201826
const previousKeyPath = task.keyPath;
@@ -1850,7 +1856,7 @@ function renderNode(
18501856

18511857
// Restore the context. We assume that this will be restored by the inner
18521858
// functions in case nothing throws so we don't use "finally" here.
1853-
task.blockedSegment.formatContext = previousFormatContext;
1859+
task.formatContext = previousFormatContext;
18541860
task.legacyContext = previousLegacyContext;
18551861
task.context = previousContext;
18561862
task.keyPath = previousKeyPath;
@@ -1882,7 +1888,7 @@ function renderNode(
18821888

18831889
// Restore the context. We assume that this will be restored by the inner
18841890
// functions in case nothing throws so we don't use "finally" here.
1885-
task.blockedSegment.formatContext = previousFormatContext;
1891+
task.formatContext = previousFormatContext;
18861892
task.legacyContext = previousLegacyContext;
18871893
task.context = previousContext;
18881894
task.keyPath = previousKeyPath;
@@ -1896,7 +1902,7 @@ function renderNode(
18961902
}
18971903
// Restore the context. We assume that this will be restored by the inner
18981904
// functions in case nothing throws so we don't use "finally" here.
1899-
task.blockedSegment.formatContext = previousFormatContext;
1905+
task.formatContext = previousFormatContext;
19001906
task.legacyContext = previousLegacyContext;
19011907
task.context = previousContext;
19021908
task.keyPath = previousKeyPath;
@@ -2474,11 +2480,11 @@ function flushSegmentContainer(
24742480
writeStartSegment(
24752481
destination,
24762482
request.renderState,
2477-
segment.formatContext,
2483+
segment.parentFormatContext,
24782484
segment.id,
24792485
);
24802486
flushSegment(request, destination, segment);
2481-
return writeEndSegment(destination, segment.formatContext);
2487+
return writeEndSegment(destination, segment.parentFormatContext);
24822488
}
24832489

24842490
function flushCompletedBoundary(

0 commit comments

Comments
 (0)