Bug 78084

Summary: SVGLoad event fires too early
Product: WebKit Reporter: Nikolas Zimmermann <zimmermann>
Component: SVGAssignee: Nikolas Zimmermann <zimmermann>
Status: RESOLVED FIXED    
Severity: Normal CC: dglazkov, morrita, podivilov, webkit.review.bot, zimmermann
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on: 77736    
Bug Blocks: 78002    
Attachments:
Description Flags
Patch morrita: review+, webkit.review.bot: commit-queue-

Description Nikolas Zimmermann 2012-02-08 00:29:18 PST
SVGLoad event fires too early, making it impossible to use the vanilla repaint.js harness (runRepaintTest). We're using a hack called runSVGRepaintTest() at the moment in trunk, which runs runRepaintTest() from a 0ms timer, which is not reliable.
Our SVGLoad handling is actually quite good, we respect externalResourcesRequired="true/false" for <image> & <script> elements, and SVGLoad events for all kind of SVG elements (rect/g/etc..).
The main difference between HTML onload and SVG onload is that HTMLs event is a "window event", thus dispatched through DOMWindow (eg. <body onload="alert(event.target)" will yield Document, <svg onload="alert(evt.target)"> will say SVGSVGElement).

Consider:
<svg onload="alert('1')>
<g onload="alert('2)">
<rect onload="alert('3')"/>
</svg>

As soon as the <rect> finishes parsing (SVGElement::finishedParsingChildren), it's SVGLoad event is fired. So first you'll see '3', then '2', then '1'.
When using

<svg onload="alert('1')>
<g onload="alert('2)">
<image xlink:href="someExternal.jpg" onload="alert('3')"/>
</svg>

Will yield the same SVGLoad order. When using <image externalREsourcesRequired="true", first the '1' will fire, then '3', then '2', all as expected and specified in SVG.

The spec says:
"The event is triggered at the point at which the user agent has fully parsed the element and its descendants and is ready to act appropriately upon that element, such as being ready to render the element to the target device. Referenced external resources that are required must be loaded, parsed and ready to render before the event is triggered. Optional external resources are not required to be ready for the event to be triggered."

What we don't implement correctly is the first part of the first sentence: "and is ready to act appropriately upon that element, such as being ready to render the element to the target device".
We currently fire the SVGLoad event, right after </svg> is seen, if no externalResourceRequired="true" attributes are set anywhere. This is not wrong, but not correct for WebKit, as we're not yet "ready to render".

HTML fires its window onload event from Document::implicitClose(), where it calls Document::dispatchWindowLoadEvent. At this point we're ready to render. So I'm now aligning the timing of the outermost <svg> elements SVGLoad event, to be equal to HTML.
This lets use use the repaint.js harness w/o any special SVG tricks.
Comment 1 Nikolas Zimmermann 2012-02-08 00:56:34 PST
Created attachment 126023 [details]
Patch
Comment 2 Hajime Morrita 2012-02-08 01:37:42 PST
- It looks now it is possible to for the load event to be fired not only from <svg> but also
   from non-<svg> outermost elements. I'd love to have tests to cover such case.

- The decision whether event should be fired or not is scattered to many places like
   finishParsingChildren() and part of dispatchSVGLoadEventToOutermostSVGElements().
   How about to tweak the parameter of sendSVGLoadEventIfPossible into something like enum, 
   to indicate the caller's context? Then we can make the decision inside that function.
Comment 3 Nikolas Zimmermann 2012-02-08 01:44:49 PST
(In reply to comment #2)
> - It looks now it is possible to for the load event to be fired not only from <svg> but also
>    from non-<svg> outermost elements. I'd love to have tests to cover such case.
We have such tests cases, see eg. svg/custom/loadevents*
The SVGLoad event is always fireable for any SVG element, not just outermost - that's a key difference between HTML/SVG load listeners. HTML onload always means listening to a window event, unlike for SVG, where its per element.

> - The decision whether event should be fired or not is scattered to many places like
>    finishParsingChildren() and part of dispatchSVGLoadEventToOutermostSVGElements().
>    How about to tweak the parameter of sendSVGLoadEventIfPossible into something like enum, 
>    to indicate the caller's context? Then we can make the decision inside that function.
Suggestion is not bad, but  I'd like to keep it as simple as possible for now, to continue working on the SVG repaint test fixes - we can come back later and refactor this, once we consider eg. delayed SVGLoad events for <use> / <feImage> etc, which we don't support at the moment.
Comment 4 WebKit Review Bot 2012-02-08 01:47:49 PST
Comment on attachment 126023 [details]
Patch

Attachment 126023 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/11462325

New failing tests:
svg/custom/repaint-on-image-bounds-change.svg
Comment 5 Hajime Morrita 2012-02-08 02:15:19 PST
Comment on attachment 126023 [details]
Patch

Okay. R+ed for now. Please skip chromium stuff before landing.
Comment 6 Nikolas Zimmermann 2012-02-08 02:19:51 PST
(In reply to comment #5)
> (From update of attachment 126023 [details])
> Okay. R+ed for now. Please skip chromium stuff before landing.
Thanks a lot, will do!
Comment 7 Nikolas Zimmermann 2012-02-08 02:22:15 PST
Committed r107057: <http://trac.webkit.org/changeset/107057>
Comment 8 Pavel Podivilov 2012-02-08 04:42:22 PST
repaint-on-image-bounds-change.svg still has wrong image in chromium: http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=svg%2Fcustom%2Frepaint-on-image-bounds-change.svg&showExpectations=true
Comment 9 Nikolas Zimmermann 2012-02-08 04:48:24 PST
(In reply to comment #8)
> repaint-on-image-bounds-change.svg still has wrong image in chromium: http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=svg%2Fcustom%2Frepaint-on-image-bounds-change.svg&showExpectations=true
Oh the test in svg/custom, and svg/dynamic-updates haven't moved yet to the new repainting harness. They're all still flaky. A patch fixing this will come soon.
Comment 10 Nikolas Zimmermann 2012-02-09 03:45:31 PST
(In reply to comment #9)
> (In reply to comment #8)
> > repaint-on-image-bounds-change.svg still has wrong image in chromium: http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=svg%2Fcustom%2Frepaint-on-image-bounds-change.svg&showExpectations=true
> Oh the test in svg/custom, and svg/dynamic-updates haven't moved yet to the new repainting harness. They're all still flaky. A patch fixing this will come soon.
Bug 77736 fixed the tests in svg/custom - this problem should be gone now, can you confirm?
Comment 11 Nikolas Zimmermann 2012-02-09 03:47:02 PST
(In reply to comment #10)
> (In reply to comment #9)
> > (In reply to comment #8)
> > > repaint-on-image-bounds-change.svg still has wrong image in chromium: http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=svg%2Fcustom%2Frepaint-on-image-bounds-change.svg&showExpectations=true
> > Oh the test in svg/custom, and svg/dynamic-updates haven't moved yet to the new repainting harness. They're all still flaky. A patch fixing this will come soon.
> Bug 77736 fixed the tests in svg/custom - this problem should be gone now, can you confirm?
Sorry, I meant to say 78115.
Comment 12 Nikolas Zimmermann 2012-02-09 04:27:22 PST
(In reply to comment #10)
> Bug 77736 fixed the tests in svg/custom - this problem should be gone now, can you confirm?
I checked on my own, it passes now! Closing bug.