@samitouri / QOS-React / commits / 1bb056363c

[Fizz] Use RequestInstance constructor for resuming (#30947)

We added enough fields to need a constructor instead of inline object in V8. We didn't update the resumeRequest path though so it wasn't using the constructor and had a different hidden class.

Sebastian Markbåge committed Sep 11, 2024 at 11:35 UTC 1bb056363c02fa9d188cc1122595d1587aa59d86
1 file changed +54 -67
packages/react-server/src/ReactFizzServer.js
+54 -67
@@ -401,7 +401,6 @@ function noop(): void {}
401
402 function RequestInstance(
403 this: $FlowFixMe,
404 - children: ReactNodeList,
404 resumableState: ResumableState,
405 renderState: RenderState,
406 rootFormatContext: FormatContext,
@@ -447,38 +446,6 @@ function RequestInstance(
446 if (__DEV__) {
447 this.didWarnForKey = null;
448 }
450 - // This segment represents the root fallback.
451 - const rootSegment = createPendingSegment(
452 - this,
453 - 0,
454 - null,
455 - rootFormatContext,
456 - // Root segments are never embedded in Text on either edge
457 - false,
458 - false,
459 - );
460 - // There is no parent so conceptually, we're unblocked to flush this segment.
461 - rootSegment.parentFlushed = true;
462 - const rootTask = createRenderTask(
463 - this,
464 - null,
465 - children,
466 - -1,
467 - null,
468 - rootSegment,
469 - null,
470 - abortSet,
471 - null,
472 - rootFormatContext,
473 - rootContextSnapshot,
474 - emptyTreeContext,
475 - null,
476 - false,
477 - emptyContextObject,
478 - null,
479 - );
480 - pushComponentStack(rootTask);
481 - pingedTasks.push(rootTask);
449 }
450
451 export function createRequest(
@@ -496,8 +463,7 @@ export function createRequest(
463 formState: void | null | ReactFormState<any, any>,
464 ): Request {
465 // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
499 - return new RequestInstance(
500 - children,
466 + const request: Request = new RequestInstance(
467 resumableState,
468 renderState,
469 rootFormatContext,
@@ -510,6 +476,40 @@ export function createRequest(
476 onPostpone,
477 formState,
478 );
479 +
480 + // This segment represents the root fallback.
481 + const rootSegment = createPendingSegment(
482 + request,
483 + 0,
484 + null,
485 + rootFormatContext,
486 + // Root segments are never embedded in Text on either edge
487 + false,
488 + false,
489 + );
490 + // There is no parent so conceptually, we're unblocked to flush this segment.
491 + rootSegment.parentFlushed = true;
492 + const rootTask = createRenderTask(
493 + request,
494 + null,
495 + children,
496 + -1,
497 + null,
498 + rootSegment,
499 + null,
500 + request.abortableTasks,
501 + null,
502 + rootFormatContext,
503 + rootContextSnapshot,
504 + emptyTreeContext,
505 + null,
506 + false,
507 + emptyContextObject,
508 + null,
509 + );
510 + pushComponentStack(rootTask);
511 + request.pingedTasks.push(rootTask);
512 + return request;
513 }
514
515 export function createPrerenderRequest(
@@ -559,35 +559,22 @@ export function resumeRequest(
559 onFatalError: void | ((error: mixed) => void),
560 onPostpone: void | ((reason: string, postponeInfo: PostponeInfo) => void),
561 ): Request {
562 - const pingedTasks: Array<Task> = [];
563 - const abortSet: Set<Task> = new Set();
564 - const request: Request = {
565 - destination: null,
566 - flushScheduled: false,
567 - resumableState: postponedState.resumableState,
562 + // $FlowFixMe[invalid-constructor]: the shapes are exact here but Flow doesn't like constructors
563 + const request: Request = new RequestInstance(
564 + postponedState.resumableState,
565 renderState,
569 - rootFormatContext: postponedState.rootFormatContext,
570 - progressiveChunkSize: postponedState.progressiveChunkSize,
571 - status: OPEN,
572 - fatalError: null,
573 - nextSegmentId: postponedState.nextSegmentId,
574 - allPendingTasks: 0,
575 - pendingRootTasks: 0,
576 - completedRootSegment: null,
577 - abortableTasks: abortSet,
578 - pingedTasks: pingedTasks,
579 - clientRenderedBoundaries: ([]: Array<SuspenseBoundary>),
580 - completedBoundaries: ([]: Array<SuspenseBoundary>),
581 - partialBoundaries: ([]: Array<SuspenseBoundary>),
582 - trackedPostpones: null,
583 - onError: onError === undefined ? defaultErrorHandler : onError,
584 - onPostpone: onPostpone === undefined ? noop : onPostpone,
585 - onAllReady: onAllReady === undefined ? noop : onAllReady,
586 - onShellReady: onShellReady === undefined ? noop : onShellReady,
587 - onShellError: onShellError === undefined ? noop : onShellError,
588 - onFatalError: onFatalError === undefined ? noop : onFatalError,
589 - formState: null,
590 - };
566 + postponedState.rootFormatContext,
567 + postponedState.progressiveChunkSize,
568 + onError,
569 + onAllReady,
570 + onShellReady,
571 + onShellError,
572 + onFatalError,
573 + onPostpone,
574 + null,
575 + );
576 + request.nextSegmentId = postponedState.nextSegmentId;
577 +
578 if (typeof postponedState.replaySlots === 'number') {
579 const resumedId = postponedState.replaySlots;
580 // We have a resume slot at the very root. This is effectively just a full rerender.
@@ -611,7 +598,7 @@ export function resumeRequest(
598 null,
599 rootSegment,
600 null,
614 - abortSet,
601 + request.abortableTasks,
602 null,
603 postponedState.rootFormatContext,
604 rootContextSnapshot,
@@ -622,7 +609,7 @@ export function resumeRequest(
609 null,
610 );
611 pushComponentStack(rootTask);
625 - pingedTasks.push(rootTask);
612 + request.pingedTasks.push(rootTask);
613 return request;
614 }
615
@@ -639,7 +626,7 @@ export function resumeRequest(
626 -1,
627 null,
628 null,
642 - abortSet,
629 + request.abortableTasks,
630 null,
631 postponedState.rootFormatContext,
632 rootContextSnapshot,
@@ -650,7 +637,7 @@ export function resumeRequest(
637 null,
638 );
639 pushComponentStack(rootTask);
653 - pingedTasks.push(rootTask);
640 + request.pingedTasks.push(rootTask);
641 return request;
642 }
643