Bug 220231

Summary: REGRESSION: animated iframe painted blank
Product: WebKit Reporter: Mathieu Hofman <hofman+webkit>
Component: AnimationsAssignee: Simon Fraser (smfr) <simon.fraser>
Status: RESOLVED FIXED    
Severity: Normal CC: andybons, dino, graouts, simon.fraser, webkit-bug-importer, zalan
Priority: P1 Keywords: InRadar
Version: Safari 14   
Hardware: Unspecified   
OS: Unspecified   
URL: https://hofman-stripe-payments-demo.appspot.com/?stripeStaticLayer=true&stripeTransitionFix=false
See Also: https://bugs.webkit.org/show_bug.cgi?id=220498
Attachments:
Description Flags
Screen capture of the reproduction of the CSS animation bug
none
Screen capture of the reproduction of the Javascript animation bug
none
iframe painted when window dragged to built-in display
none
iframe not painted when window dragged to other display
none
Patch none

Mathieu Hofman
Reported 2021-01-03 18:52:11 PST
Created attachment 416919 [details] Screen capture of the reproduction of the CSS animation bug We have a couple iframe paint bugs in Safari we've finally been able to consistently reproduce on some systems. In Safari 13+ (and possibly earlier versions), a loaded iframe faded into view through a JavaScript based animation (e.g. `$.fadeIn()`) would sometimes paint blank. In those cases, no composite layer for the iframe would exist. Any reflow of the container would trigger the iframe paint. Applying a transform or other CSS style that would force a composite layer for the iframe would prevent the occurrence of this bug. To reproduce: - In Safari 13+ , open https://hofman-stripe-payments-demo.appspot.com/jq-repro/?stripeStaticLayer=false&stripeTransitionFix=false - Click CB (the frame is painted correctly) - Refresh - Click CB again (make sure network cache is not disabled if devtools are open) - Observe blank painted iframe where card input should be - The iframe is actually functional, can be filed through keyboard or autofill. - Any resize of the container (window) caused the iframe to be painted However, the workaround to force a composite layer through CSS style causes another blank paint bug in Safari 14+. If the loaded iframe is animated into view through a CSS transition on an ancestor, the iframe is painted blank. Without the forced promotion to its own composition layer, the iframe would render fine. A forced reflow of the parent doesn't help repaint the iframe since it has its own composite layer. We have implemented another workaround to listen for transition start events on any ancestor and force a reflow on the iframe itself, however it's very hacky, and we are worried of other undiscovered cases where this bug might trigger. To reproduce: - In Safari 14+, open https://hofman-stripe-payments-demo.appspot.com/?stripeStaticLayer=true&stripeTransitionFix=false - Observe the card iframe painted blank - The iframe is actually functional, can be filed through keyboard or autofill. We've had multiple bug reports from our users about these issues including: - https://github.com/stripe/react-stripe-js/issues/136 - https://github.com/stripe/stripe-js/issues/128 - https://github.com/stripe/stripe-js/issues/113 - https://github.com/stripe/react-stripe-elements/issues/35 While the above reproductions are for desktop Safari, we've had reports of these bugs also happening on iPhone and iPad. There are some triggers we still don't fully understand. For the first reproduction, we don't know why caching seem to have an impact. For the second reproduction, the issue only manifests if the iframe has loaded before the CSS transition starts (the reproduction delays CSS animation until load for consistency). We unfortunately haven't been able to create more minimal reproductions.
Attachments
Screen capture of the reproduction of the CSS animation bug (796.48 KB, video/quicktime)
2021-01-03 18:52 PST, Mathieu Hofman
no flags
Screen capture of the reproduction of the Javascript animation bug (976.02 KB, video/quicktime)
2021-01-03 18:52 PST, Mathieu Hofman
no flags
iframe painted when window dragged to built-in display (6.69 MB, video/quicktime)
2021-01-04 13:19 PST, Mathieu Hofman
no flags
iframe not painted when window dragged to other display (5.13 MB, video/quicktime)
2021-01-04 13:20 PST, Mathieu Hofman
no flags
Patch (5.38 KB, patch)
2021-01-05 15:34 PST, Simon Fraser (smfr)
no flags
Mathieu Hofman
Comment 1 2021-01-03 18:52:55 PST
Created attachment 416920 [details] Screen capture of the reproduction of the Javascript animation bug
Alexey Proskuryakov
Comment 2 2021-01-04 09:49:06 PST
> - In Safari 13+ , open https://hofman-stripe-payments-demo.appspot.com/jq-repro/?stripeStaticLayer=false&stripeTransitionFix=false I can reproduce this issue with a recent WebKit build that I have on my machine. > - In Safari 14+, open https://hofman-stripe-payments-demo.appspot.com/?stripeStaticLayer=true&stripeTransitionFix=false But I cannot reproduces this one. Perhaps it's a Safari 14 regression that's been fixed already.
Radar WebKit Bug Importer
Comment 3 2021-01-04 09:49:15 PST
Mathieu Hofman
Comment 4 2021-01-04 11:09:28 PST
> But I cannot reproduces this one. Perhaps it's a Safari 14 regression that's been fixed already. Apparently we still have inconsistent reproduction on this depending on the machine. We're trying to figure out if there is some other factor (e.g. dedicated graphics). Can you reproduce in Safari 14.0.2 (15610.3.7.1.10, 15610)? My machine is a MacBookPro15,2 i7 running macOS 10.15.7 (19H15)
Mathieu Hofman
Comment 5 2021-01-04 13:19:27 PST
Created attachment 416961 [details] iframe painted when window dragged to built-in display
Mathieu Hofman
Comment 6 2021-01-04 13:20:08 PST
Created attachment 416963 [details] iframe not painted when window dragged to other display
Mathieu Hofman
Comment 7 2021-01-04 13:22:09 PST
I believe we've isolated a necessary trigger for this bug: the window needs to be rendered on a secondary display (non-retina?), not the built-in display of the MacBook Pro. Then dragging that window to the built-in display will cause the iframe to be painted. The same is not true if dragging the window to another (non-retina?) display.
Mathieu Hofman
Comment 8 2021-01-04 14:12:12 PST
I've verified that rendering on a secondary retina monitor does not trigger this bug. It seems that the trigger for the CSS animation based bug is for the window to be rendered on a non-retina display.
Simon Fraser (smfr)
Comment 9 2021-01-05 09:28:01 PST
I can reproduce the Safari 14 version on a non-retina display.
Simon Fraser (smfr)
Comment 10 2021-01-05 11:33:15 PST
I can see that the GraphicsLayers are connected across frame boundaries, but the CALayers are not.
Simon Fraser (smfr)
Comment 11 2021-01-05 11:53:29 PST
Doesn't happen if we don't call m_graphicsLayer->setContentsVisible(false) on the iframe's layer. Hardcoding the deviceScaleFactor() to 1 makes it happen on Retina screens.
Simon Fraser (smfr)
Comment 12 2021-01-05 11:59:01 PST
Found it.
Simon Fraser (smfr)
Comment 13 2021-01-05 14:49:21 PST
The "non-retina" part is related to m_compositedBoundsOffsetFromGraphicsLayer which affects whether the iframe's GraphicsLayer uses a m_contentsClippingLayer or not.
Simon Fraser (smfr)
Comment 14 2021-01-05 15:34:43 PST
EWS
Comment 15 2021-01-05 19:55:27 PST
Committed r271191: <https://trac.webkit.org/changeset/271191> All reviewed patches have been landed. Closing bug and clearing flags on attachment 417044 [details].
Mathieu Hofman
Comment 16 2021-01-05 22:12:40 PST
Thanks for the quick turnaround. For clarification, does the patch also fix the JavaScript based animation bug present since at least Safari 13? Sorry for filing a combined bug on this one, they seemed related since our workaround for the first one triggered the second one.
Simon Fraser (smfr)
Comment 17 2021-01-06 09:29:36 PST
The Safari 13+ bug does seem to still reproduce after this fix. I'll investigate.
Simon Fraser (smfr)
Comment 18 2021-01-11 10:54:16 PST
Doing so in bug 220498.
Note You need to log in before you can comment on or make changes to this bug.