336
const ABORTED = 3;
337
const ERRORED = 4;
338
const POSTPONED = 5;
339
-const RENDERING = 6;
339
340
type Root = null;
341
342
type Segment = {
344
- status: 0 | 1 | 2 | 3 | 4 | 5 | 6,
343
+ status: 0 | 1 | 2 | 3 | 4 | 5,
344
parentFlushed: boolean, // typically a segment will be flushed by its parent, except if its parent was already flushed
345
id: number, // starts as 0 and is lazily assigned if the parent flushes early
346
+index: number, // the index within the parent's chunks or 0 at the root
380
byteSize: number, // counts the number of bytes accumulated in the shell
381
abortableTasks: Set<Task>,
382
pingedTasks: Array<Task>, // High priority tasks that should be worked on first.
383
+ currentTask: null | Task, // The task currently executing in this request.
384
// Queues to flush in order of priority
385
clientRenderedBoundaries: Array<SuspenseBoundary>, // Errored or client rendered but not yet flushed.
386
completedBoundaries: Array<SuspenseBoundary>, // Completed but not yet fully flushed boundaries to show.
539
this.byteSize = 0;
540
this.abortableTasks = abortSet;
541
this.pingedTasks = pingedTasks;
542
+ this.currentTask = null;
543
this.clientRenderedBoundaries = ([]: Array<SuspenseBoundary>);
544
this.completedBoundaries = ([]: Array<SuspenseBoundary>);
545
this.partialBoundaries = ([]: Array<SuspenseBoundary>);
1474
replaceSuspenseComponentStackWithSuspenseFallbackStack(
1475
suspenseComponentStack,
1476
);
1476
- boundarySegment.status = RENDERING;
1477
try {
1478
renderNode(request, task, fallback, -1);
1479
pushSegmentFinale(
1548
prevContext,
1549
);
1550
task.row = null;
1551
- contentRootSegment.status = RENDERING;
1552
-
1551
try {
1552
// We use the safe form because we don't handle suspending here. Only error handling.
1553
renderNode(request, task, content, -1);
1742
// faster
1743
return;
1744
}
1747
- } catch (error: mixed) {
1745
+ } catch (thrownValue: mixed) {
1746
resumedBoundary.status = CLIENT_RENDERED;
1747
+ const error = request.aborted ? request.fatalError : thrownValue;
1748
const thrownInfo = getThrownInfo(task.componentStack);
1749
const errorDigest = logRecoverableError(
1750
request,
2262
blockedSegment.preambleChildren.push(preambleSegment);
2263
task.blockedSegment = preambleSegment;
2264
try {
2266
- preambleSegment.status = RENDERING;
2265
renderNode(request, task, node, -1);
2266
pushSegmentFinale(
2267
preambleSegment.chunks,
3159
erroredReplay(
3160
request,
3161
task.blockedBoundary,
3164
- x,
3162
+ request.aborted ? request.fatalError : x,
3163
thrownInfo,
3164
childNodes,
3165
childSlots,
3674
erroredReplay(
3675
request,
3676
task.blockedBoundary,
3679
- x,
3677
+ request.aborted ? request.fatalError : x,
3678
thrownInfo,
3679
childNodes,
3680
childSlots,
4594
function abortTask(task: Task, request: Request, error: mixed): void {
4595
// This aborts the task and aborts the parent that it blocks, putting it into
4596
// client rendered mode.
4597
+ if (task === request.currentTask) {
4598
+ // This is a currently rendering Task. The render itself will abort the task.
4599
+ return;
4600
+ }
4601
const boundary = task.blockedBoundary;
4602
const segment = task.blockedSegment;
4603
if (segment !== null) {
4602
- if (segment.status === RENDERING) {
4603
- // This is the a currently rendering Segment. The render itself will
4604
- // abort the task.
4605
- return;
4606
- }
4604
segment.status = ABORTED;
4605
}
4606
5076
return;
5077
}
5078
5082
- // We track when a Segment is rendering so we can handle aborts while rendering
5083
- segment.status = RENDERING;
5079
+ const prevTask = request.currentTask;
5080
+ request.currentTask = task;
5081
5082
// We restore the context to what it was when we suspended.
5083
// We don't restore it after we leave because it's likely that we'll end up
5174
);
5175
return;
5176
} finally {
5177
+ request.currentTask = prevTask;
5178
if (__DEV__) {
5179
setCurrentTaskInDEV(prevTaskInDEV);
5180
}
5187
return;
5188
}
5189
5190
+ const prevTask = request.currentTask;
5191
+ request.currentTask = task;
5192
+
5193
// We restore the context to what it was when we suspended.
5194
// We don't restore it after we leave because it's likely that we'll end up
5195
// needing a very similar context soon again.
5268
}
5269
return;
5270
} finally {
5271
+ request.currentTask = prevTask;
5272
if (__DEV__) {
5273
setCurrentTaskInDEV(prevTaskInDEV);
5274
}