1905
return ioNode;
1906
}
1907
// Outline the IO node.
1908
- emitIOChunk(request, ioNode);
1908
+ serializeIONode(request, ioNode);
1909
// Then emit a reference to us awaiting it in the current task.
1910
request.pendingChunks++;
1911
emitDebugChunk(request, task.id, {
1942
// each occurrence. Right now we'll only track the first time it is invoked.
1943
awaitedNode.end = performance.now();
1944
}
1945
- emitIOChunk(request, awaitedNode);
1945
+ serializeIONode(request, awaitedNode);
1946
request.pendingChunks++;
1947
emitDebugChunk(request, task.id, {
1948
awaited: ((awaitedNode: any): ReactIOInfo), // This is deduped by this reference.
3493
request.writtenObjects.set(componentInfo, serializeByValueID(id));
3494
}
3495
3496
-function outlineIOInfo(request: Request, ioInfo: ReactIOInfo): void {
3496
+function emitIOInfoChunk(
3497
+ request: Request,
3498
+ id: number,
3499
+ start: number,
3500
+ end: number,
3501
+ stack: ?ReactStackTrace,
3502
+): void {
3503
if (!__DEV__) {
3504
// These errors should never make it into a build so we don't need to encode them in codes.json
3505
// eslint-disable-next-line react-internal/prod-error-codes
3506
throw new Error(
3501
- 'outlineIOInfo should never be called in production mode. This is a bug in React.',
3507
+ 'emitIOInfoChunk should never be called in production mode. This is a bug in React.',
3508
);
3509
}
3510
3505
- if (request.writtenObjects.has(ioInfo)) {
3506
- // Already written
3507
- return;
3508
- }
3509
-
3510
- // Limit the number of objects we write to prevent emitting giant props objects.
3511
let objectLimit = 10;
3512
- if (ioInfo.stack != null) {
3513
- // Ensure we have enough object limit to encode the stack trace.
3514
- objectLimit += ioInfo.stack.length;
3512
+ if (stack) {
3513
+ objectLimit += stack.length;
3514
}
3516
-
3517
- // We use the console encoding so that we can dedupe objects but don't necessarily
3518
- // use the full serialization that requires a task.
3515
const counter = {objectLimit};
3516
+ function replacer(
3517
+ this:
3518
+ | {+[key: string | number]: ReactClientValue}
3519
+ | $ReadOnlyArray<ReactClientValue>,
3520
+ parentPropertyName: string,
3521
+ value: ReactClientValue,
3522
+ ): ReactJSONValue {
3523
+ return renderConsoleValue(
3524
+ request,
3525
+ counter,
3526
+ this,
3527
+ parentPropertyName,
3528
+ value,
3529
+ );
3530
+ }
3531
3521
- // We can't serialize the ConsoleTask/Error objects so we need to omit them before serializing.
3522
- const relativeStartTimestamp = ioInfo.start - request.timeOrigin;
3523
- const relativeEndTimestamp = ioInfo.end - request.timeOrigin;
3532
+ const relativeStartTimestamp = start - request.timeOrigin;
3533
+ const relativeEndTimestamp = end - request.timeOrigin;
3534
const debugIOInfo: Omit<ReactIOInfo, 'debugTask' | 'debugStack'> = {
3535
start: relativeStartTimestamp,
3536
end: relativeEndTimestamp,
3527
- stack: ioInfo.stack,
3537
+ stack: stack,
3538
};
3529
- const id = outlineConsoleValue(request, counter, debugIOInfo);
3530
- request.writtenObjects.set(ioInfo, serializeByValueID(id));
3539
+ // $FlowFixMe[incompatible-type] stringify can return null
3540
+ const json: string = stringify(debugIOInfo, replacer);
3541
+ const row = id.toString(16) + ':J' + json + '\n';
3542
+ const processedChunk = stringToChunk(row);
3543
+ request.completedRegularChunks.push(processedChunk);
3544
}
3545
3533
-function emitIOChunk(request: Request, ioNode: IONode | PromiseNode): void {
3534
- if (!__DEV__) {
3535
- // These errors should never make it into a build so we don't need to encode them in codes.json
3536
- // eslint-disable-next-line react-internal/prod-error-codes
3537
- throw new Error(
3538
- 'outlineIOInfo should never be called in production mode. This is a bug in React.',
3539
- );
3546
+function outlineIOInfo(request: Request, ioInfo: ReactIOInfo): void {
3547
+ if (request.writtenObjects.has(ioInfo)) {
3548
+ // Already written
3549
+ return;
3550
}
3551
+ // We can't serialize the ConsoleTask/Error objects so we need to omit them before serializing.
3552
+ request.pendingChunks++;
3553
+ const id = request.nextChunkId++;
3554
+ emitIOInfoChunk(request, id, ioInfo.start, ioInfo.end, ioInfo.stack);
3555
+ request.writtenObjects.set(ioInfo, serializeByValueID(id));
3556
+}
3557
3542
- if (request.writtenObjects.has(ioNode)) {
3558
+function serializeIONode(
3559
+ request: Request,
3560
+ ioNode: IONode | PromiseNode,
3561
+): string {
3562
+ const existingRef = request.writtenObjects.get(ioNode);
3563
+ if (existingRef !== undefined) {
3564
// Already written
3544
- return;
3565
+ return existingRef;
3566
}
3567
3547
- // Limit the number of objects we write to prevent emitting giant props objects.
3548
- let objectLimit = 10;
3568
let stack = null;
3569
if (ioNode.stack !== null) {
3570
stack = filterStackTrace(request, ioNode.stack, 1);
3552
- // Ensure we have enough object limit to encode the stack trace.
3553
- objectLimit += stack.length;
3571
}
3555
-
3556
- // We use the console encoding so that we can dedupe objects but don't necessarily
3557
- // use the full serialization that requires a task.
3558
- const counter = {objectLimit};
3559
-
3560
- // We can't serialize the ConsoleTask/Error objects so we need to omit them before serializing.
3561
- const relativeStartTimestamp = ioNode.start - request.timeOrigin;
3562
- const relativeEndTimestamp = ioNode.end - request.timeOrigin;
3563
- const debugIOInfo: Omit<ReactIOInfo, 'debugTask' | 'debugStack'> = {
3564
- start: relativeStartTimestamp,
3565
- end: relativeEndTimestamp,
3566
- stack: stack,
3567
- };
3568
- const id = outlineConsoleValue(request, counter, debugIOInfo);
3569
- request.writtenObjects.set(ioNode, serializeByValueID(id));
3572
+ request.pendingChunks++;
3573
+ const id = request.nextChunkId++;
3574
+ emitIOInfoChunk(request, id, ioNode.start, ioNode.end, stack);
3575
+ const ref = serializeByValueID(id);
3576
+ request.writtenObjects.set(ioNode, ref);
3577
+ return ref;
3578
}
3579
3580
function emitTypedArrayChunk(