@@ -80,6 +80,7 @@ import isArray from 'shared/isArray';
8080import {
8181 clientRenderBoundary as clientRenderFunction ,
8282 completeBoundary as completeBoundaryFunction ,
83+ completeBoundaryUpgradeToViewTransitions as upgradeToViewTransitionsInstruction ,
8384 completeBoundaryWithStyles as styleInsertionFunction ,
8485 completeSegment as completeSegmentFunction ,
8586 formReplaying as formReplayingRuntime ,
@@ -123,14 +124,16 @@ const ScriptStreamingFormat: StreamingFormat = 0;
123124const DataStreamingFormat : StreamingFormat = 1 ;
124125
125126export type InstructionState = number ;
126- const NothingSent /* */ = 0b0000000 ;
127- const SentCompleteSegmentFunction /* */ = 0b0000001 ;
128- const SentCompleteBoundaryFunction /* */ = 0b0000010 ;
129- const SentClientRenderFunction /* */ = 0b0000100 ;
130- const SentStyleInsertionFunction /* */ = 0b0001000 ;
131- const SentFormReplayingRuntime /* */ = 0b0010000 ;
132- const SentCompletedShellId /* */ = 0b0100000 ;
133- const SentMarkShellTime /* */ = 0b1000000 ;
127+ const NothingSent /* */ = 0b000000000 ;
128+ const SentCompleteSegmentFunction /* */ = 0b000000001 ;
129+ const SentCompleteBoundaryFunction /* */ = 0b000000010 ;
130+ const SentClientRenderFunction /* */ = 0b000000100 ;
131+ const SentStyleInsertionFunction /* */ = 0b000001000 ;
132+ const SentFormReplayingRuntime /* */ = 0b000010000 ;
133+ const SentCompletedShellId /* */ = 0b000100000 ;
134+ const SentMarkShellTime /* */ = 0b001000000 ;
135+ const NeedUpgradeToViewTransitions /* */ = 0b010000000 ;
136+ const SentUpgradeToViewTransitions /* */ = 0b100000000 ;
134137
135138// Per request, global state that is not contextual to the rendering subtree.
136139// This cannot be resumed and therefore should only contain things that are
@@ -742,12 +745,13 @@ const HTML_COLGROUP_MODE = 9;
742745
743746type InsertionMode = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ;
744747
745- const NO_SCOPE = /* */ 0b00000 ;
746- const NOSCRIPT_SCOPE = /* */ 0b00001 ;
747- const PICTURE_SCOPE = /* */ 0b00010 ;
748- const FALLBACK_SCOPE = /* */ 0b00100 ;
749- const EXIT_SCOPE = /* */ 0b01000 ; // A direct Instance below a Suspense fallback is the only thing that can "exit"
750- const ENTER_SCOPE = /* */ 0b10000 ; // A direct Instance below Suspense content is the only thing that can "enter"
748+ const NO_SCOPE = /* */ 0b000000 ;
749+ const NOSCRIPT_SCOPE = /* */ 0b000001 ;
750+ const PICTURE_SCOPE = /* */ 0b000010 ;
751+ const FALLBACK_SCOPE = /* */ 0b000100 ;
752+ const EXIT_SCOPE = /* */ 0b001000 ; // A direct Instance below a Suspense fallback is the only thing that can "exit"
753+ const ENTER_SCOPE = /* */ 0b010000 ; // A direct Instance below Suspense content is the only thing that can "enter"
754+ const UPDATE_SCOPE = /* */ 0b100000 ; // Inside a scope that applies "update" ViewTransitions if anything mutates here.
751755
752756// Everything not listed here are tracked for the whole subtree as opposed to just
753757// until the next Instance.
@@ -926,8 +930,15 @@ function getSuspenseViewTransition(
926930}
927931
928932export function getSuspenseFallbackFormatContext (
933+ resumableState : ResumableState ,
929934 parentContext : FormatContext ,
930935) : FormatContext {
936+ if ( parentContext . tagScope & UPDATE_SCOPE ) {
937+ // If we're rendering a Suspense in fallback mode and that is inside a ViewTransition,
938+ // which hasn't disabled updates, then revealing it might animate the parent so we need
939+ // the ViewTransition instructions.
940+ resumableState . instructions |= NeedUpgradeToViewTransitions ;
941+ }
931942 return createFormatContext (
932943 parentContext . insertionMode ,
933944 parentContext . selectedValue ,
@@ -937,6 +948,7 @@ export function getSuspenseFallbackFormatContext(
937948}
938949
939950export function getSuspenseContentFormatContext (
951+ resumableState : ResumableState ,
940952 parentContext : FormatContext ,
941953) : FormatContext {
942954 return createFormatContext (
@@ -948,6 +960,7 @@ export function getSuspenseContentFormatContext(
948960}
949961
950962export function getViewTransitionFormatContext (
963+ resumableState : ResumableState ,
951964 parentContext : FormatContext ,
952965 update : ?string ,
953966 enter : ?string ,
@@ -983,14 +996,26 @@ export function getViewTransitionFormatContext(
983996 // exit because enter/exit will take precedence and if it's deeply nested
984997 // it just animates along whatever the parent does when disabled.
985998 share = null ;
986- } else if ( share == null ) {
987- share = 'auto ';
999+ } else {
1000+ if ( share == null ) {
1001+ share = 'auto ';
1002+ }
1003+ if ( parentContext . tagScope & FALLBACK_SCOPE ) {
1004+ // If we have an explicit name and share is not disabled, and we're inside
1005+ // a fallback, then that fallback might pair with content and so we might need
1006+ // the ViewTransition instructions to animate between them.
1007+ resumableState . instructions |= NeedUpgradeToViewTransitions ;
1008+ }
9881009 }
9891010 if ( ! ( parentContext . tagScope & EXIT_SCOPE ) ) {
9901011 exit = null ; // exit is only relevant for the first ViewTransition inside fallback
1012+ } else {
1013+ resumableState . instructions |= NeedUpgradeToViewTransitions ;
9911014 }
9921015 if ( ! ( parentContext . tagScope & ENTER_SCOPE ) ) {
9931016 enter = null ; // enter is only relevant for the first ViewTransition inside content
1017+ } else {
1018+ resumableState . instructions |= NeedUpgradeToViewTransitions ;
9941019 }
9951020 const viewTransition : ViewTransitionContext = {
9961021 update,
@@ -1001,7 +1026,12 @@ export function getViewTransitionFormatContext(
10011026 autoName,
10021027 nameIdx : 0 ,
10031028 } ;
1004- const subtreeScope = parentContext . tagScope & SUBTREE_SCOPE ;
1029+ let subtreeScope = parentContext . tagScope & SUBTREE_SCOPE ;
1030+ if ( update !== 'none' ) {
1031+ subtreeScope |= UPDATE_SCOPE ;
1032+ } else {
1033+ subtreeScope &= ~ UPDATE_SCOPE ;
1034+ }
10051035 return createFormatContext (
10061036 parentContext . insertionMode ,
10071037 parentContext . selectedValue ,
@@ -4780,9 +4810,8 @@ export function writeCompletedSegmentInstruction(
47804810const completeBoundaryScriptFunctionOnly = stringToPrecomputedChunk (
47814811 completeBoundaryFunction ,
47824812) ;
4783- const completeBoundaryScript1Full = stringToPrecomputedChunk (
4784- completeBoundaryFunction + '$RC("' ,
4785- ) ;
4813+ const completeBoundaryUpgradeToViewTransitionsInstruction =
4814+ stringToPrecomputedChunk ( upgradeToViewTransitionsInstruction ) ;
47864815const completeBoundaryScript1Partial = stringToPrecomputedChunk ( '$RC("' ) ;
47874816
47884817const completeBoundaryWithStylesScript1FullPartial = stringToPrecomputedChunk (
@@ -4814,6 +4843,10 @@ export function writeCompletedBoundaryInstruction(
48144843 hoistableState : HoistableState ,
48154844) : boolean {
48164845 const requiresStyleInsertion = renderState . stylesToHoist ;
4846+ const requiresViewTransitions =
4847+ enableViewTransition &&
4848+ ( resumableState . instructions & NeedUpgradeToViewTransitions ) !==
4849+ NothingSent ;
48174850 // If necessary stylesheets will be flushed with this instruction.
48184851 // Any style tags not yet hoisted in the Document will also be hoisted.
48194852 // We reset this state since after this instruction executes all styles
@@ -4842,6 +4875,17 @@ export function writeCompletedBoundaryInstruction(
48424875 resumableState . instructions |= SentCompleteBoundaryFunction ;
48434876 writeChunk ( destination , completeBoundaryScriptFunctionOnly ) ;
48444877 }
4878+ if (
4879+ requiresViewTransitions &&
4880+ ( resumableState . instructions & SentUpgradeToViewTransitions ) ===
4881+ NothingSent
4882+ ) {
4883+ resumableState . instructions |= SentUpgradeToViewTransitions ;
4884+ writeChunk (
4885+ destination ,
4886+ completeBoundaryUpgradeToViewTransitionsInstruction ,
4887+ ) ;
4888+ }
48454889 if (
48464890 ( resumableState . instructions & SentStyleInsertionFunction ) ===
48474891 NothingSent
@@ -4857,10 +4901,20 @@ export function writeCompletedBoundaryInstruction(
48574901 NothingSent
48584902 ) {
48594903 resumableState . instructions |= SentCompleteBoundaryFunction ;
4860- writeChunk ( destination , completeBoundaryScript1Full ) ;
4861- } else {
4862- writeChunk ( destination , completeBoundaryScript1Partial ) ;
4904+ writeChunk ( destination , completeBoundaryScriptFunctionOnly ) ;
4905+ }
4906+ if (
4907+ requiresViewTransitions &&
4908+ ( resumableState . instructions & SentUpgradeToViewTransitions ) ===
4909+ NothingSent
4910+ ) {
4911+ resumableState . instructions |= SentUpgradeToViewTransitions ;
4912+ writeChunk (
4913+ destination ,
4914+ completeBoundaryUpgradeToViewTransitionsInstruction ,
4915+ ) ;
48634916 }
4917+ writeChunk ( destination , completeBoundaryScript1Partial ) ;
48644918 }
48654919 } else {
48664920 if ( requiresStyleInsertion ) {
0 commit comments