Bug 239418

Summary: Incorrect clipping when animation is present.
Product: WebKit Reporter: Hubert SABLONNIÈRE <hubert.sablonniere>
Component: CompositingAssignee: Simon Fraser (smfr) <simon.fraser>
Status: NEW ---    
Severity: Normal CC: bfulgham, graouts, koivisto, rik, simon.fraser, webkit-bug-importer, zalan
Priority: P2 Keywords: InRadar
Version: Safari 15   
Hardware: All   
OS: All   
Attachments:
Description Flags
reduction-test.html
none
Incorrect clipping
none
Testcase with will-change: z-index none

Description Hubert SABLONNIÈRE 2022-04-16 05:57:40 PDT
Created attachment 457747 [details]
reduction-test.html

We encoutered a inconsistent CSS behaviour between Chromium/Firefox vs. Webkit

The different behavior is observed when we combine an animation on the opacity with a position:absolute element (which is itself a child of an overflow:hidden element).

We tried to reduce our code to something really small to help the team figuring this out (see attachment).

We put different variations in this reduction test:

* animation:NO - overflow:hidden (same in Chromium/Firefox/Webkit)
* animation:NO - overflow:visible (same in Chromium/Firefox/Webkit)
* animation:YES - overflow:visible (same in Chromium/Firefox/Webkit)
* animation:YES - overflow:hidden (different in Chromium/Firefox vs. Webkit)

We observed the problem on:

* Safari on iPad 15.3/605.1.15
* Gnome Epiphany on Linux 42.1 (WebkitGTK 2.36.0)

We think it was working before (something like Safari 6 months ago) but it's not easy for us to test on older versions of Safari.
Comment 1 zalan 2022-04-16 06:43:49 PDT
Created attachment 457748 [details]
Incorrect clipping

Thanks for filing this issue (and the great test case!). It indeed looks incorrect in WebKit.

It seems that animation (incorrectly) imposes clipping on the absolute child (see attached test reduction). I went all the way back to r256320 (over 2 years ago) and it was still broken there.
Comment 2 Radar WebKit Bug Importer 2022-04-16 06:45:31 PDT
<rdar://problem/91848849>
Comment 3 Hubert SABLONNIÈRE 2022-04-16 06:55:55 PDT
Wow, I'm impressed by your reactivity!!
Thanks for creating a better test case, and looking into the past versions.
Comment 4 zalan 2022-04-16 07:10:06 PDT
The composited layer for the inner (animated) box clips the out-of-flow child box (while the animation property does not make it a containing block) 

layer 0x135028830 scrollableArea 0x1350802c0 at (0,0) size 1144x695 (composited [root], bounds=at (0,0) size 1144x695, drawsContent=1, paints into ancestor=0)
  RenderView 0x13c0007b0 at (0,0) size 1144x695
 positive z-order list (1)
  layer 0x135028f50 scrollableArea 0x135080360 at (0,0) size 1144x695
    RenderBlock 0x13c001640 {HTML} at (0,0) size 1144x695
      RenderBody 0x13c001780 {BODY} at (8,8) size 1128x679
   positive z-order list (2)
    layer 0x135029080 at (8,8) size 300x300
      RenderBlock (relative positioned) 0x13c0041e0 {DIV} at (0,0) size 300x300 [bgcolor=#008000] class="container"
    layer 0x1350291b0 scrollableArea 0x135080400 at (8,8) size 100x100 (composited [animation], bounds=at (0,0) size 100x100, drawsContent=1, paints into ancestor=0)
      RenderBlock 0x13c004320 {DIV} at (0,0) size 100x100 class="middle"
     positive z-order list (1)
      layer 0x1350292e0 at (18,18) size 280x280
        RenderBlock (positioned) 0x13c004460 {DIV} at (10,10) size 280x280 [border: (3px solid #0000FF)] class="inner"

The layer tree looks the same when animation is changed to some other, composited layer triggering property like transform: translateZ. However in this case the middle layer forms a containing block for the out-of-flow child and clipping is expected.
Comment 5 Simon Fraser (smfr) 2022-04-22 21:17:37 PDT
Created attachment 458197 [details]
Testcase with will-change: z-index
Comment 6 Simon Fraser (smfr) 2022-04-22 21:23:32 PDT
S---------C-c-- -- tb---- ------ 30 30 0x113170700 (0,0) width=780 height=844 [SA 0x113045120] (layerID 482) {sc 30} RenderView 0x1480007b0
S-----------c-- -- tb---- lg---- 30 30   + 0x113170960 (0,0) width=780 height=844 [SA 0x113045620] RenderBlock 0x148001640 HTML 0x148000f20
--------------- -- ------ lg---- 30 30     + 0x113170a90 (28,20) width=300 height=300 RenderBlock (relative positioned) 0x148003190 DIV 0x148002b60 class='container'
S---------C---- -- ------ lg-c-- 30 30     + 0x113170bc0 (0,0) width=25 height=25 (layerID 485) RenderBlock (positioned) 0x1480032d0 DIV 0x148002bf0 class='trigger'
S-O-------C---- -- tb---- lg-c-- 30 30     + 0x113170cf0 (10,0) width=102 height=102 [SA 0x1130456c0] (layerID 488) overlap RenderBlock 0x148003410 DIV 0x148002c80 class='middle'
--------------- -- ------ lg---- 30 30       + 0x113170e20 (10,10) width=280 height=280 RenderBlock (positioned) 0x148003550 DIV 0x148002e60 class='inner'

The inner layer isn't composited; it paints into its paint-order ancestor, which is 0x113170cf0. However, when computing the bounds of that layer, we've taken overflow:hidden into account, despite it having non-clipped descendants. I think that's the bug.