@@ -80,6 +80,7 @@ import isArray from 'shared/isArray';
80
80
import {
81
81
clientRenderBoundary as clientRenderFunction ,
82
82
completeBoundary as completeBoundaryFunction ,
83
+ completeBoundaryUpgradeToViewTransitions as upgradeToViewTransitionsInstruction ,
83
84
completeBoundaryWithStyles as styleInsertionFunction ,
84
85
completeSegment as completeSegmentFunction ,
85
86
formReplaying as formReplayingRuntime ,
@@ -123,14 +124,16 @@ const ScriptStreamingFormat: StreamingFormat = 0;
123
124
const DataStreamingFormat : StreamingFormat = 1 ;
124
125
125
126
export 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 ;
134
137
135
138
// Per request, global state that is not contextual to the rendering subtree.
136
139
// This cannot be resumed and therefore should only contain things that are
@@ -742,12 +745,13 @@ const HTML_COLGROUP_MODE = 9;
742
745
743
746
type InsertionMode = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ;
744
747
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.
751
755
752
756
// Everything not listed here are tracked for the whole subtree as opposed to just
753
757
// until the next Instance.
@@ -926,8 +930,15 @@ function getSuspenseViewTransition(
926
930
}
927
931
928
932
export function getSuspenseFallbackFormatContext (
933
+ resumableState : ResumableState ,
929
934
parentContext : FormatContext ,
930
935
) : 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
+ }
931
942
return createFormatContext (
932
943
parentContext . insertionMode ,
933
944
parentContext . selectedValue ,
@@ -937,6 +948,7 @@ export function getSuspenseFallbackFormatContext(
937
948
}
938
949
939
950
export function getSuspenseContentFormatContext (
951
+ resumableState : ResumableState ,
940
952
parentContext : FormatContext ,
941
953
) : FormatContext {
942
954
return createFormatContext (
@@ -948,6 +960,7 @@ export function getSuspenseContentFormatContext(
948
960
}
949
961
950
962
export function getViewTransitionFormatContext (
963
+ resumableState : ResumableState ,
951
964
parentContext : FormatContext ,
952
965
update : ?string ,
953
966
enter : ?string ,
@@ -983,14 +996,26 @@ export function getViewTransitionFormatContext(
983
996
// exit because enter/exit will take precedence and if it's deeply nested
984
997
// it just animates along whatever the parent does when disabled.
985
998
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
+ }
988
1009
}
989
1010
if ( ! ( parentContext . tagScope & EXIT_SCOPE ) ) {
990
1011
exit = null ; // exit is only relevant for the first ViewTransition inside fallback
1012
+ } else {
1013
+ resumableState . instructions |= NeedUpgradeToViewTransitions ;
991
1014
}
992
1015
if ( ! ( parentContext . tagScope & ENTER_SCOPE ) ) {
993
1016
enter = null ; // enter is only relevant for the first ViewTransition inside content
1017
+ } else {
1018
+ resumableState . instructions |= NeedUpgradeToViewTransitions ;
994
1019
}
995
1020
const viewTransition : ViewTransitionContext = {
996
1021
update,
@@ -1001,7 +1026,12 @@ export function getViewTransitionFormatContext(
1001
1026
autoName,
1002
1027
nameIdx : 0 ,
1003
1028
} ;
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
+ }
1005
1035
return createFormatContext (
1006
1036
parentContext . insertionMode ,
1007
1037
parentContext . selectedValue ,
@@ -4780,9 +4810,8 @@ export function writeCompletedSegmentInstruction(
4780
4810
const completeBoundaryScriptFunctionOnly = stringToPrecomputedChunk (
4781
4811
completeBoundaryFunction ,
4782
4812
) ;
4783
- const completeBoundaryScript1Full = stringToPrecomputedChunk (
4784
- completeBoundaryFunction + '$RC("' ,
4785
- ) ;
4813
+ const completeBoundaryUpgradeToViewTransitionsInstruction =
4814
+ stringToPrecomputedChunk ( upgradeToViewTransitionsInstruction ) ;
4786
4815
const completeBoundaryScript1Partial = stringToPrecomputedChunk ( '$RC("' ) ;
4787
4816
4788
4817
const completeBoundaryWithStylesScript1FullPartial = stringToPrecomputedChunk (
@@ -4814,6 +4843,10 @@ export function writeCompletedBoundaryInstruction(
4814
4843
hoistableState : HoistableState ,
4815
4844
) : boolean {
4816
4845
const requiresStyleInsertion = renderState . stylesToHoist ;
4846
+ const requiresViewTransitions =
4847
+ enableViewTransition &&
4848
+ ( resumableState . instructions & NeedUpgradeToViewTransitions ) !==
4849
+ NothingSent ;
4817
4850
// If necessary stylesheets will be flushed with this instruction.
4818
4851
// Any style tags not yet hoisted in the Document will also be hoisted.
4819
4852
// We reset this state since after this instruction executes all styles
@@ -4842,6 +4875,17 @@ export function writeCompletedBoundaryInstruction(
4842
4875
resumableState . instructions |= SentCompleteBoundaryFunction ;
4843
4876
writeChunk ( destination , completeBoundaryScriptFunctionOnly ) ;
4844
4877
}
4878
+ if (
4879
+ requiresViewTransitions &&
4880
+ ( resumableState . instructions & SentUpgradeToViewTransitions ) ===
4881
+ NothingSent
4882
+ ) {
4883
+ resumableState . instructions |= SentUpgradeToViewTransitions ;
4884
+ writeChunk (
4885
+ destination ,
4886
+ completeBoundaryUpgradeToViewTransitionsInstruction ,
4887
+ ) ;
4888
+ }
4845
4889
if (
4846
4890
( resumableState . instructions & SentStyleInsertionFunction ) ===
4847
4891
NothingSent
@@ -4857,10 +4901,20 @@ export function writeCompletedBoundaryInstruction(
4857
4901
NothingSent
4858
4902
) {
4859
4903
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
+ ) ;
4863
4916
}
4917
+ writeChunk ( destination , completeBoundaryScript1Partial ) ;
4864
4918
}
4865
4919
} else {
4866
4920
if ( requiresStyleInsertion ) {
0 commit comments