Changeset 225862 in webkit
- Timestamp:
- Dec 13, 2017 12:01:48 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r225852 r225862 1 2017-12-13 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Implement the "updating the finished state" procedure 4 https://bugs.webkit.org/show_bug.cgi?id=180743 5 <rdar://problem/36017232> 6 7 Reviewed by Simon Fraser. 8 9 Rebase some WPT expectations with minor progressions due to exposing the "onfinish" property. 10 11 * http/wpt/web-animations/interfaces/Animation/idlharness-expected.txt: 12 1 13 2017-12-13 Matt Lewis <jlewis3@apple.com> 2 14 -
trunk/LayoutTests/http/wpt/web-animations/interfaces/Animation/idlharness-expected.txt
r225812 r225862 15 15 PASS Animation interface: attribute ready 16 16 PASS Animation interface: attribute finished 17 FAIL Animation interface: attribute onfinish assert_true: The prototype object must have a property "onfinish" expected true got false 17 PASS Animation interface: attribute onfinish 18 18 FAIL Animation interface: attribute oncancel assert_true: The prototype object must have a property "oncancel" expected true got false 19 19 FAIL Animation interface: operation cancel() assert_own_property: interface prototype object missing non-static operation expected property "cancel" missing … … 33 33 PASS Animation interface: new Animation() must inherit property "ready" with the proper type 34 34 PASS Animation interface: new Animation() must inherit property "finished" with the proper type 35 FAIL Animation interface: new Animation() must inherit property "onfinish" with the proper type assert_inherits: property "onfinish" not found in prototype chain 35 PASS Animation interface: new Animation() must inherit property "onfinish" with the proper type 36 36 FAIL Animation interface: new Animation() must inherit property "oncancel" with the proper type assert_inherits: property "oncancel" not found in prototype chain 37 37 FAIL Animation interface: new Animation() must inherit property "cancel()" with the proper type assert_inherits: property "cancel" not found in prototype chain -
trunk/Source/WebCore/ChangeLog
r225859 r225862 1 2017-12-13 Antoine Quint <graouts@apple.com> 2 3 [Web Animations] Implement the "updating the finished state" procedure 4 https://bugs.webkit.org/show_bug.cgi?id=180743 5 <rdar://problem/36017232> 6 7 Reviewed by Simon Fraser. 8 9 The Web Animations spec defines a procedure for "updating the finished state", which should run as the timeline time 10 changes and is responsible for ultimately triggering finish events and fulfil the "finished" promise. The procedure 11 allows for two flags to control its behavior: didSeek and synchronouslyNotify. When synchronouslyNotify is true, the 12 "finish notification steps" procedure is ran right away, otherwise it's queued as a microtask. 13 14 In this patch we introduce the notion of "hold time", which is the time held while an animation is paused. It will be 15 set by the pause() and play() method in future patches. 16 17 * animation/DocumentTimeline.cpp: 18 (WebCore::DocumentTimeline::updateAnimations): Update the finished state as the timeline time changes with both flags 19 set to false. 20 * animation/WebAnimation.cpp: 21 (WebCore::WebAnimation::currentTime const): Add a private currentTime(bool) variant which allows for the hold time to 22 be ignored in case updateFinishedState() was called with the didSeek flag set to false. 23 (WebCore::WebAnimation::updateFinishedState): Implement the procedure as specified with all spec-mandated steps inline. 24 (WebCore::WebAnimation::scheduleMicrotaskIfNeeded): Schedule a microtask to complete the "finish notification steps" 25 if we haven't scheduled a microtask before. 26 (WebCore::WebAnimation::performMicrotask): Perform the microtask if the "finish notification steps" procedure hasn't 27 been canceled after it was originally scheduled, as tracked by the m_finishNotificationStepsMicrotaskPending flag, since 28 microtasks are not presently cancelable. 29 (WebCore::WebAnimation::finishNotificationSteps): Implement the procedure as specified with all spec-mandated steps inline, 30 dispatching a "finish" events and fulfilling the "finished" promise. 31 * animation/WebAnimation.h: 32 * animation/WebAnimation.idl: 33 * dom/EventNames.h: 34 1 35 2017-12-13 Simon Fraser <simon.fraser@apple.com> 2 36 -
trunk/Source/WebCore/animation/DocumentTimeline.cpp
r225790 r225862 173 173 m_acceleratedAnimationsPendingRunningStateChange.clear(); 174 174 175 for (const auto& animation : animations()) 176 animation->updateFinishedState(WebAnimation::DidSeek::No, WebAnimation::SynchronouslyNotify::No); 177 175 178 // Time has advanced, the timing model requires invalidation now. 176 179 animationTimingModelDidChange(); -
trunk/Source/WebCore/animation/WebAnimation.cpp
r225812 r225862 31 31 #include "AnimationTimeline.h" 32 32 #include "Document.h" 33 #include "EventNames.h" 33 34 #include "JSWebAnimation.h" 34 35 #include "KeyframeEffect.h" 36 #include "Microtasks.h" 35 37 #include <wtf/text/WTFString.h> 36 38 … … 176 178 std::optional<Seconds> WebAnimation::currentTime() const 177 179 { 178 // FIXME: return the hold time when we support pausing (webkit.org/b/178932). 179 180 if (!m_timeline || !m_startTime) 180 return currentTime(RespectHoldTime::Yes); 181 } 182 183 std::optional<Seconds> WebAnimation::currentTime(RespectHoldTime respectHoldTime) const 184 { 185 // 3.4.4. The current time of an animation 186 // https://drafts.csswg.org/web-animations-1/#the-current-time-of-an-animation 187 188 // The current time is calculated from the first matching condition from below: 189 190 // If the animation's hold time is resolved, the current time is the animation's hold time. 191 if (respectHoldTime == RespectHoldTime::Yes && m_holdTime) 192 return m_holdTime; 193 194 // If any of the following are true: 195 // 1. the animation has no associated timeline, or 196 // 2. the associated timeline is inactive, or 197 // 3. the animation's start time is unresolved. 198 // The current time is an unresolved time value. 199 if (!m_timeline || !m_timeline->currentTime() || !m_startTime) 181 200 return std::nullopt; 182 201 183 auto timelineTime = m_timeline->currentTime(); 184 if (!timelineTime) 185 return std::nullopt; 186 187 return (timelineTime.value() - m_startTime.value()) * m_playbackRate; 202 // Otherwise, current time = (timeline time - start time) * playback rate 203 return (m_timeline->currentTime().value() - m_startTime.value()) * m_playbackRate; 188 204 } 189 205 … … 274 290 } 275 291 292 void WebAnimation::updateFinishedState(DidSeek didSeek, SynchronouslyNotify synchronouslyNotify) 293 { 294 // 3.4.14. Updating the finished state 295 // https://drafts.csswg.org/web-animations-1/#updating-the-finished-state 296 297 // 1. Let the unconstrained current time be the result of calculating the current time substituting an unresolved time value 298 // for the hold time if did seek is false. If did seek is true, the unconstrained current time is equal to the current time. 299 auto unconstrainedCurrentTime = currentTime(didSeek == DidSeek::Yes ? RespectHoldTime::Yes : RespectHoldTime::No); 300 auto endTime = effectEndTime(); 301 302 // 2. If all three of the following conditions are true, 303 // - the unconstrained current time is resolved, and 304 // - animation's start time is resolved, and 305 // - animation does not have a pending play task or a pending pause task, 306 if (unconstrainedCurrentTime && startTime() && !pending()) { 307 // then update animation's hold time based on the first matching condition for animation from below, if any: 308 if (m_playbackRate > 0 && unconstrainedCurrentTime >= endTime) { 309 // If animation playback rate > 0 and unconstrained current time is greater than or equal to target effect end, 310 // If did seek is true, let the hold time be the value of unconstrained current time. 311 if (didSeek == DidSeek::Yes) 312 m_holdTime = unconstrainedCurrentTime; 313 // If did seek is false, let the hold time be the maximum value of previous current time and target effect end. If the previous current time is unresolved, let the hold time be target effect end. 314 else if (!m_previousCurrentTime) 315 m_holdTime = endTime; 316 else 317 m_holdTime = std::max(m_previousCurrentTime.value(), endTime); 318 } else if (m_playbackRate < 0 && unconstrainedCurrentTime <= 0_s) { 319 // If animation playback rate < 0 and unconstrained current time is less than or equal to 0, 320 // If did seek is true, let the hold time be the value of unconstrained current time. 321 if (didSeek == DidSeek::Yes) 322 m_holdTime = unconstrainedCurrentTime; 323 // If did seek is false, let the hold time be the minimum value of previous current time and zero. If the previous current time is unresolved, let the hold time be zero. 324 else if (!m_previousCurrentTime) 325 m_holdTime = 0_s; 326 else 327 m_holdTime = std::min(m_previousCurrentTime.value(), 0_s); 328 } else if (m_playbackRate && m_timeline && m_timeline->currentTime()) { 329 // If animation playback rate ≠ 0, and animation is associated with an active timeline, 330 // Perform the following steps: 331 // 1. If did seek is true and the hold time is resolved, let animation's start time be equal to the result of evaluating timeline time - (hold time / playback rate) 332 // where timeline time is the current time value of timeline associated with animation. 333 if (didSeek == DidSeek::Yes && m_holdTime) 334 setStartTime(m_timeline->currentTime().value() - (m_holdTime.value() / m_playbackRate)); 335 // 2. Let the hold time be unresolved. 336 m_holdTime = std::nullopt; 337 } 338 } 339 340 // 3. Set the previous current time of animation be the result of calculating its current time. 341 m_previousCurrentTime = currentTime(); 342 343 // 4. Let current finished state be true if the play state of animation is finished. Otherwise, let it be false. 344 auto currentFinishedState = playState() == PlayState::Finished; 345 346 // 5. If current finished state is true and the current finished promise is not yet resolved, perform the following steps: 347 if (currentFinishedState && !m_finishedPromise.isFulfilled()) { 348 if (synchronouslyNotify == SynchronouslyNotify::Yes) { 349 // If synchronously notify is true, cancel any queued microtask to run the finish notification steps for this animation, 350 // and run the finish notification steps immediately. 351 m_finishNotificationStepsMicrotaskPending = false; 352 finishNotificationSteps(); 353 } else if (!m_finishNotificationStepsMicrotaskPending) { 354 // Otherwise, if synchronously notify is false, queue a microtask to run finish notification steps for animation unless there 355 // is already a microtask queued to run those steps for animation. 356 m_finishNotificationStepsMicrotaskPending = true; 357 scheduleMicrotaskIfNeeded(); 358 } 359 } 360 361 // 6. If current finished state is false and animation's current finished promise is already resolved, set animation's current 362 // finished promise to a new (pending) Promise object. 363 if (!currentFinishedState && m_finishedPromise.isFulfilled()) 364 m_finishedPromise.clear(); 365 } 366 367 void WebAnimation::scheduleMicrotaskIfNeeded() 368 { 369 if (m_scheduledMicrotask) 370 return; 371 372 m_scheduledMicrotask = true; 373 MicrotaskQueue::mainThreadQueue().append(std::make_unique<VoidMicrotask>(std::bind(&WebAnimation::performMicrotask, this))); 374 } 375 376 void WebAnimation::performMicrotask() 377 { 378 m_scheduledMicrotask = false; 379 if (!m_finishNotificationStepsMicrotaskPending) 380 return; 381 382 m_finishNotificationStepsMicrotaskPending = false; 383 finishNotificationSteps(); 384 } 385 386 void WebAnimation::finishNotificationSteps() 387 { 388 // 3.4.14. Updating the finished state 389 // https://drafts.csswg.org/web-animations-1/#finish-notification-steps 390 391 // Let finish notification steps refer to the following procedure: 392 // 1. If animation's play state is not equal to finished, abort these steps. 393 if (playState() != PlayState::Finished) 394 return; 395 396 // 2. Resolve animation's current finished promise object with animation. 397 m_finishedPromise.resolve(*this); 398 399 // 3. Create an AnimationPlaybackEvent, finishEvent. 400 // 4. Set finishEvent's type attribute to finish. 401 // 5. Set finishEvent's currentTime attribute to the current time of animation. 402 // 6. Set finishEvent's timelineTime attribute to the current time of the timeline with which animation is associated. 403 // If animation is not associated with a timeline, or the timeline is inactive, let timelineTime be null. 404 // 7. If animation has a document for timing, then append finishEvent to its document for timing's pending animation event 405 // queue along with its target, animation. For the scheduled event time, use the result of converting animation's target 406 // effect end to an origin-relative time. 407 // Otherwise, queue a task to dispatch finishEvent at animation. The task source for this task is the DOM manipulation task source. 408 enqueueAnimationPlaybackEvent(eventNames().finishEvent, currentTime(), m_timeline ? m_timeline->currentTime() : std::nullopt); 409 } 410 276 411 Seconds WebAnimation::timeToNextRequiredTick(Seconds timelineTime) const 277 412 { -
trunk/Source/WebCore/animation/WebAnimation.h
r225812 r225862 85 85 void startOrStopAccelerated(); 86 86 87 enum class DidSeek { Yes, No }; 88 enum class SynchronouslyNotify { Yes, No }; 89 void updateFinishedState(DidSeek, SynchronouslyNotify); 90 87 91 String description(); 88 92 … … 93 97 explicit WebAnimation(Document&); 94 98 99 enum class RespectHoldTime { Yes, No }; 100 95 101 void enqueueAnimationPlaybackEvent(const AtomicString&, std::optional<Seconds>, std::optional<Seconds>); 96 102 Seconds effectEndTime() const; 97 103 WebAnimation& readyPromiseResolve(); 98 104 WebAnimation& finishedPromiseResolve(); 105 std::optional<Seconds> currentTime(RespectHoldTime) const; 106 void finishNotificationSteps(); 107 void scheduleMicrotaskIfNeeded(); 108 void performMicrotask(); 99 109 100 110 RefPtr<AnimationEffect> m_effect; 101 111 RefPtr<AnimationTimeline> m_timeline; 112 std::optional<Seconds> m_previousCurrentTime; 102 113 std::optional<Seconds> m_startTime; 114 std::optional<Seconds> m_holdTime; 103 115 double m_playbackRate { 1 }; 104 116 bool m_isStopped { false }; 117 bool m_finishNotificationStepsMicrotaskPending; 118 bool m_scheduledMicrotask; 105 119 ReadyPromise m_readyPromise; 106 120 FinishedPromise m_finishedPromise; -
trunk/Source/WebCore/animation/WebAnimation.idl
r225812 r225862 46 46 readonly attribute AnimationPlayState playState; 47 47 readonly attribute boolean pending; 48 attribute EventHandler onfinish; 48 49 readonly attribute Promise<WebAnimation> ready; 49 50 readonly attribute Promise<WebAnimation> finished; -
trunk/Source/WebCore/dom/EventNames.h
r225849 r225862 117 117 macro(exit) \ 118 118 macro(fetch) \ 119 macro(finish) \ 119 120 macro(focus) \ 120 121 macro(focusin) \
Note: See TracChangeset
for help on using the changeset viewer.