@@ -235,17 +235,60 @@ function warnForPropDifference(
235235 }
236236}
237237
238+ function hasViewTransition ( htmlElement : HTMLElement ) : boolean {
239+ return ! ! (
240+ htmlElement . getAttribute ( 'vt-share' ) ||
241+ htmlElement . getAttribute ( 'vt-exit' ) ||
242+ htmlElement . getAttribute ( 'vt-enter' ) ||
243+ htmlElement . getAttribute ( 'vt-update' )
244+ ) ;
245+ }
246+
247+ function isExpectedViewTransitionName ( htmlElement : HTMLElement ) : boolean {
248+ if ( ! hasViewTransition ( htmlElement ) ) {
249+ // We didn't expect to see a view transition name applied.
250+ return false ;
251+ }
252+ const expectedVtName = htmlElement . getAttribute ( 'vt-name' ) ;
253+ const actualVtName : string = ( htmlElement . style : any ) [ 'view-transition-name' ] ;
254+ if ( expectedVtName ) {
255+ return expectedVtName === actualVtName ;
256+ } else {
257+ // Auto-generated name.
258+ // TODO: If Fizz starts applying a prefix to this name, we need to consider that.
259+ return actualVtName . startsWith ( '_T_' ) ;
260+ }
261+ }
262+
238263function warnForExtraAttributes (
239264 domElement : Element ,
240265 attributeNames : Set < string > ,
241266 serverDifferences : { [ propName : string ] : mixed } ,
242267) {
243268 if ( __DEV__ ) {
244269 attributeNames . forEach ( function ( attributeName ) {
245- serverDifferences [ getPropNameFromAttributeName ( attributeName ) ] =
246- attributeName === 'style'
247- ? getStylesObjectFromElement ( domElement )
248- : domElement . getAttribute ( attributeName ) ;
270+ if ( attributeName === 'style' ) {
271+ if ( domElement . getAttribute ( attributeName ) === '' ) {
272+ // Skip empty style. It's fine.
273+ return ;
274+ }
275+ const htmlElement = ( ( domElement : any ) : HTMLElement ) ;
276+ const style = htmlElement . style ;
277+ const isOnlyVTStyles =
278+ ( style . length === 1 && style [ 0 ] === 'view-transition-name' ) ||
279+ ( style . length === 2 &&
280+ style [ 0 ] === 'view-transition-class' &&
281+ style [ 1 ] === 'view-transition-name' ) ;
282+ if ( isOnlyVTStyles && isExpectedViewTransitionName ( htmlElement ) ) {
283+ // If the only extra style was the view-transition-name that we applied from the Fizz
284+ // runtime, then we should ignore it.
285+ } else {
286+ serverDifferences . style = getStylesObjectFromElement ( domElement ) ;
287+ }
288+ } else {
289+ serverDifferences [ getPropNameFromAttributeName ( attributeName ) ] =
290+ domElement . getAttribute ( attributeName ) ;
291+ }
249292 } ) ;
250293 }
251294}
@@ -1977,13 +2020,21 @@ function getStylesObjectFromElement(domElement: Element): {
19772020 [ styleName : string ] : string ,
19782021} {
19792022 const serverValueInObjectForm : { [ prop : string ] : string } = { } ;
1980- const style = ( ( domElement : any ) : HTMLElement ) . style ;
2023+ const htmlElement : HTMLElement = ( domElement : any ) ;
2024+ const style = htmlElement . style ;
19812025 for ( let i = 0 ; i < style . length ; i ++ ) {
19822026 const styleName : string = style [ i ] ;
19832027 // TODO: We should use the original prop value here if it is equivalent.
19842028 // TODO: We could use the original client capitalization if the equivalent
19852029 // other capitalization exists in the DOM.
1986- serverValueInObjectForm [ styleName ] = style . getPropertyValue ( styleName ) ;
2030+ if (
2031+ styleName === 'view-transition-name' &&
2032+ isExpectedViewTransitionName ( htmlElement )
2033+ ) {
2034+ // This is a view transition name added by the Fizz runtime, not the user's props.
2035+ } else {
2036+ serverValueInObjectForm [ styleName ] = style . getPropertyValue ( styleName ) ;
2037+ }
19872038 }
19882039 return serverValueInObjectForm ;
19892040}
@@ -2018,6 +2069,20 @@ function diffHydratedStyles(
20182069 return ;
20192070 }
20202071
2072+ if (
2073+ // Trailing semi-colon means this was regenerated.
2074+ normalizedServerValue [ normalizedServerValue . length - 1 ] === ';' &&
2075+ // TODO: Should we just ignore any style if the style as been manipulated?
2076+ hasViewTransition ( ( domElement : any ) )
2077+ ) {
2078+ // If this had a view transition we might have applied a view transition
2079+ // name/class and removed it. If that happens, the style attribute gets
2080+ // regenerated from the style object. This means we've lost the format
2081+ // that we sent from the server and is unable to diff it. We just treat
2082+ // it as passing even if it should be a mismatch in this edge case.
2083+ return ;
2084+ }
2085+
20212086 // Otherwise, we create the object from the DOM for the diff view.
20222087 serverDifferences . style = getStylesObjectFromElement ( domElement ) ;
20232088}
0 commit comments