Changeset 233583 in webkit
- Timestamp:
- Jul 6, 2018, 11:31:12 AM (8 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 9 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/webanimations/leak-document-with-web-animation-expected.txt (added)
-
LayoutTests/webanimations/leak-document-with-web-animation.html (added)
-
LayoutTests/webanimations/resources (added)
-
LayoutTests/webanimations/resources/web-animation-leak-iframe.html (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/animation/AnimationTimeline.cpp (modified) (1 diff)
-
Source/WebCore/animation/DeclarativeAnimation.cpp (modified) (1 diff)
-
Source/WebCore/animation/DeclarativeAnimation.h (modified) (2 diffs)
-
Source/WebCore/animation/DocumentAnimationScheduler.cpp (modified) (1 diff)
-
Source/WebCore/animation/DocumentTimeline.cpp (modified) (2 diffs)
-
Source/WebCore/animation/WebAnimation.cpp (modified) (6 diffs)
-
Source/WebCore/animation/WebAnimation.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r233581 r233583 1 2018-07-06 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Using a Web Animation leaks the Document 4 https://bugs.webkit.org/show_bug.cgi?id=187088 5 <rdar://problem/41392046> 6 7 Reviewed by Darin Adler. 8 9 * webanimations/leak-document-with-web-animation-expected.txt: Added. 10 * webanimations/leak-document-with-web-animation.html: Added. 11 * webanimations/resources/web-animation-leak-iframe.html: Added. 12 1 13 2018-07-06 Saam Barati <sbarati@apple.com> 2 14 -
trunk/Source/WebCore/ChangeLog
r233578 r233583 1 2018-07-06 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Using a Web Animation leaks the Document 4 https://bugs.webkit.org/show_bug.cgi?id=187088 5 <rdar://problem/41392046> 6 7 Reviewed by Darin Adler. 8 9 Test: webanimations/leak-document-with-web-animation.html 10 11 We need to ensure that any remaining animation is cleared when the DocumentTimeline is detached from its Document. 12 We rename WebAnimation::prepareAnimationForRemoval() to WebAnimation::remove() since it really actively disassociates 13 the animation from its timeline. 14 15 An earlier version of this patch (r233349) was rolled out due to crashes caught in the ASan configuration. The following 16 changes were made to make it safe: 17 18 - We protect the DocumentAnimationScheduler instance in displayRefreshFired() against code that might run in a 19 requestAnimationFrame() callback that would trigger the object to be deleted. 20 21 - We protect the WebAnimation instance in remove() against setEffectInternal() or setTimelineInternal() potentially 22 causing the object to be deleted. Similar protections were addede to setEffect() and setTimeline(). 23 24 - We changed ~DocumentTimeline() to a default implementation to ensure it calls ~DisplayRefreshMonitorClient() 25 to avoid callbacks after the object has been marked for deletion. 26 27 28 * animation/AnimationTimeline.cpp: 29 (WebCore::AnimationTimeline::removeAnimationsForElement): We no longer need the call to removeAnimation() 30 since the new WebAnimation::remove() method will also set the timeline to null which will eventually call 31 removeAnimation() on the disassociated timeline. 32 * animation/DeclarativeAnimation.cpp: 33 (WebCore::DeclarativeAnimation::remove): 34 (WebCore::DeclarativeAnimation::prepareAnimationForRemoval): Deleted. 35 * animation/DeclarativeAnimation.h: 36 * animation/DocumentAnimationScheduler.cpp: 37 (WebCore::DocumentAnimationScheduler::displayRefreshFired): 38 * animation/DocumentTimeline.cpp: 39 (WebCore::DocumentTimeline::detachFromDocument): Call remove() on all known animations. 40 (WebCore::DocumentTimeline::~DocumentTimeline): Deleted. 41 * animation/WebAnimation.cpp: 42 (WebCore::WebAnimation::remove): Set the timeline to null to fully disassociate this animation from its timeline. 43 (WebCore::WebAnimation::setEffect): 44 (WebCore::WebAnimation::setEffectInternal): 45 (WebCore::WebAnimation::setTimeline): Factor the internal timeline-association code out of this JS API method so 46 that we can call this code without any JS-facing implications. 47 (WebCore::WebAnimation::setTimelineInternal): 48 (WebCore::WebAnimation::prepareAnimationForRemoval): Deleted. 49 * animation/WebAnimation.h: 50 1 51 2018-07-06 Daniel Bates <dabates@apple.com> 2 52 -
trunk/Source/WebCore/animation/AnimationTimeline.cpp
r233361 r233583 177 177 void AnimationTimeline::removeAnimationsForElement(Element& element) 178 178 { 179 for (auto& animation : animationsForElement(element)) { 180 animation->prepareAnimationForRemoval(); 181 removeAnimation(animation.releaseNonNull()); 182 } 179 for (auto& animation : animationsForElement(element)) 180 animation->remove(); 183 181 } 184 182 -
trunk/Source/WebCore/animation/DeclarativeAnimation.cpp
r233361 r233583 50 50 } 51 51 52 void DeclarativeAnimation::prepareAnimationForRemoval() 53 { 54 WebAnimation::prepareAnimationForRemoval(); 52 void DeclarativeAnimation::remove() 53 { 55 54 m_eventQueue.close(); 55 WebAnimation::remove(); 56 56 } 57 57 -
trunk/Source/WebCore/animation/DeclarativeAnimation.h
r233361 r233583 46 46 void setBackingAnimation(const Animation&); 47 47 void invalidateDOMEvents(Seconds elapsedTime = 0_s); 48 void prepareAnimationForRemoval() final;49 48 50 49 void setTimeline(RefPtr<AnimationTimeline>&&) final; … … 60 59 AnimationEffectReadOnly::Phase phaseWithoutEffect() const; 61 60 void enqueueDOMEvent(const AtomicString&, Seconds); 61 void remove() final; 62 62 63 63 Element& m_target; -
trunk/Source/WebCore/animation/DocumentAnimationScheduler.cpp
r233394 r233583 76 76 return; 77 77 78 // This object could be deleted after scripts in the the requestAnimationFrame callbacks are executed. 79 auto protectedThis = makeRef(*this); 80 78 81 m_isFiring = true; 79 82 m_lastTimestamp = Seconds(m_document->domWindow()->nowTimestamp()); -
trunk/Source/WebCore/animation/DocumentTimeline.cpp
r233500 r233583 56 56 } 57 57 58 DocumentTimeline::~DocumentTimeline() 59 { 60 } 58 DocumentTimeline::~DocumentTimeline() = default; 61 59 62 60 void DocumentTimeline::detachFromDocument() … … 65 63 m_eventDispatchTaskQueue.close(); 66 64 m_animationScheduleTimer.stop(); 65 66 auto& animationsToRemove = animations(); 67 while (!animationsToRemove.isEmpty()) 68 animationsToRemove.first()->remove(); 69 67 70 m_document = nullptr; 68 71 } -
trunk/Source/WebCore/animation/WebAnimation.cpp
r233519 r233583 72 72 } 73 73 74 void WebAnimation::prepareAnimationForRemoval() 75 { 74 void WebAnimation::remove() 75 { 76 // This object could be deleted after either clearing the effect or timeline relationship. 77 auto protectedThis = makeRef(*this); 76 78 setEffectInternal(nullptr); 79 setTimelineInternal(nullptr); 77 80 } 78 81 … … 129 132 // while the effect was set via the API, the element still has a transition or animation set up and we must 130 133 // not break the timeline-to-animation relationship. 134 135 // This object could be deleted after clearing the effect relationship. 136 auto protectedThis = makeRef(*this); 131 137 setEffectInternal(WTFMove(newEffect), isDeclarativeAnimation()); 132 138 … … 140 146 void WebAnimation::setEffectInternal(RefPtr<AnimationEffectReadOnly>&& newEffect, bool doNotRemoveFromTimeline) 141 147 { 142 auto oldEffect = m_effect; 143 144 m_effect = WTFMove(newEffect); 148 if (m_effect == newEffect) 149 return; 150 151 auto oldEffect = std::exchange(m_effect, WTFMove(newEffect)); 145 152 146 153 Element* previousTarget = nullptr; … … 178 185 if (m_startTime) 179 186 setHoldTime(std::nullopt); 180 181 if (m_timeline)182 m_timeline->removeAnimation(*this);183 184 if (timeline)185 timeline->addAnimation(*this);186 187 187 188 if (is<KeyframeEffectReadOnly>(m_effect)) { … … 199 200 } 200 201 201 m_timeline = WTFMove(timeline); 202 // This object could be deleted after clearing the timeline relationship. 203 auto protectedThis = makeRef(*this); 204 setTimelineInternal(WTFMove(timeline)); 202 205 203 206 setSuspended(is<DocumentTimeline>(m_timeline) && downcast<DocumentTimeline>(*m_timeline).animationsAreSuspended()); … … 208 211 // and the synchronously notify flag set to false. 209 212 updateFinishedState(DidSeek::No, SynchronouslyNotify::No); 213 } 214 215 void WebAnimation::setTimelineInternal(RefPtr<AnimationTimeline>&& timeline) 216 { 217 if (m_timeline == timeline) 218 return; 219 220 if (m_timeline) 221 m_timeline->removeAnimation(*this); 222 223 m_timeline = WTFMove(timeline); 224 225 if (m_timeline) 226 m_timeline->addAnimation(*this); 210 227 } 211 228 -
trunk/Source/WebCore/animation/WebAnimation.h
r233361 r233583 64 64 AnimationEffectReadOnly* effect() const { return m_effect.get(); } 65 65 void setEffect(RefPtr<AnimationEffectReadOnly>&&); 66 void setEffectInternal(RefPtr<AnimationEffectReadOnly>&&, bool = false);67 66 AnimationTimeline* timeline() const { return m_timeline.get(); } 68 67 virtual void setTimeline(RefPtr<AnimationTimeline>&&); … … 118 117 void setSuspended(bool); 119 118 bool isSuspended() const { return m_isSuspended; } 120 virtual void prepareAnimationForRemoval();119 virtual void remove(); 121 120 122 121 String description(); … … 157 156 void runPendingPlayTask(); 158 157 void resetPendingTasks(); 159 158 void setEffectInternal(RefPtr<AnimationEffectReadOnly>&&, bool = false); 159 void setTimelineInternal(RefPtr<AnimationTimeline>&&); 160 160 161 String m_id; 161 162 RefPtr<AnimationEffectReadOnly> m_effect;
Note:
See TracChangeset
for help on using the changeset viewer.