Title: [286555] trunk
Revision
286555
Author
[email protected]
Date
2021-12-06 11:30:57 -0800 (Mon, 06 Dec 2021)

Log Message

[Web Animations] Add a way to run scripted animations
https://bugs.webkit.org/show_bug.cgi?id=233869
rdar://85983542

Reviewed by Dean Jackson.

Source/WebCore:

Tests: webanimations/custom-effect/custom-effect.html
       webanimations/custom-effect/document-timeline-animate.html

This patch adds two new Web-exposed features to allow authors to write callback-based animations
leveraging the full power of the Web Animations model.

First, we add a new AnimationEffect subclass which wraps a callback to be executed on every tick
of the associated animation's timeline: CustomEffect. It can be constructed by providing a JS function
as its first parameter, and either a number or a dictionary to provide timing properties for the effect.
This is similar to how KeyframeEffect will accept a keyframes object and then timing data. The callback
is provided the effect progress as its sole parameter. Web authors can use this new interface as follows:

    const animation = new Animation;
    animation.effect = new CustomEffect(progress => { … }, 1000);
    animation.play();

Second, to make starting callback-based animations more straightforward and in a very similar fashion
to how keyframe animations can be initiated on an element using Element.animate(), we introduce a new
animate() method on DocumentTimeline, allowing the previous exmaple to be written as:

    const animation = document.timeline.animate(progress => { … }, 1000);

This simple approach allows Web authors to move past the simple use of requestAnimationFrame() and harness
the Web Animations timing model which will let them pause and resume animations, seek them, control their
playback rate, apply easing, respond to the "finished" promise, etc.

The code itself is very simple, CustomEffect is simply an AnimationEffect subclass that indicates that it's
always interested in scheduling updates while active using the ticksContinouslyWhileActive() method. This
means that all the scheduling logic contained in WebAnimation and AnimationEffect applies, allowing callbacks
to not be fired when the animation is paused or when the page is suspended, or fired sparingly when a steps()
timing function is specified.

* CMakeLists.txt:
* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* Headers.cmake:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* animation/AnimationEffect.h:
(WebCore::AnimationEffect::isCustomEffect const):
* animation/CustomAnimationOptions.h: Added.
* animation/CustomAnimationOptions.idl: Added.
* animation/CustomEffect.cpp: Added.
(WebCore::CustomEffect::create):
(WebCore::CustomEffect::CustomEffect):
(WebCore::CustomEffect::animationDidTick):
* animation/CustomEffect.h: Added.
(WebCore::CustomEffect::~CustomEffect):
* animation/CustomEffect.idl: Added.
* animation/CustomEffectCallback.h: Added.
* animation/CustomEffectCallback.idl: Added.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::animate):
* animation/DocumentTimeline.h:
* animation/DocumentTimeline.idl:
* bindings/js/WebCoreBuiltinNames.h:

Source/WTF:

Add a new experimental feature for the CustomEffect interface.

* Scripts/Preferences/WebPreferencesExperimental.yaml:

LayoutTests:

Add tests for the new CustomEffect interface and the document.timeline.animate() method.
These are written using WPT libraries such that they may be upstreamed to the WPT repository
in the future if and when the CustomEffect interface is standardized.

* platform/win/TestExpectations:
* webanimations/custom-effect/custom-effect-expected.txt: Added.
* webanimations/custom-effect/custom-effect.html: Added.
* webanimations/custom-effect/document-timeline-animate-expected.txt: Added.
* webanimations/custom-effect/document-timeline-animate.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (286554 => 286555)


--- trunk/LayoutTests/ChangeLog	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/LayoutTests/ChangeLog	2021-12-06 19:30:57 UTC (rev 286555)
@@ -1,3 +1,21 @@
+2021-12-06  Antoine Quint  <[email protected]>
+
+        [Web Animations] Add a way to run scripted animations
+        https://bugs.webkit.org/show_bug.cgi?id=233869
+        rdar://85983542
+
+        Reviewed by Dean Jackson.
+
+        Add tests for the new CustomEffect interface and the document.timeline.animate() method.
+        These are written using WPT libraries such that they may be upstreamed to the WPT repository
+        in the future if and when the CustomEffect interface is standardized.
+
+        * platform/win/TestExpectations:
+        * webanimations/custom-effect/custom-effect-expected.txt: Added.
+        * webanimations/custom-effect/custom-effect.html: Added.
+        * webanimations/custom-effect/document-timeline-animate-expected.txt: Added.
+        * webanimations/custom-effect/document-timeline-animate.html: Added.
+
 2021-12-06  Rob Buis  <[email protected]>
 
         Null check in shouldUseBreakElement

Modified: trunk/LayoutTests/platform/win/TestExpectations (286554 => 286555)


--- trunk/LayoutTests/platform/win/TestExpectations	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/LayoutTests/platform/win/TestExpectations	2021-12-06 19:30:57 UTC (rev 286555)
@@ -4760,3 +4760,5 @@
 webkit.org/b/232321 imported/mozilla/svg/viewBox-and-pattern-03.svg [ Pass Crash ]
 
 webkit.org/b/232703 webanimations/no-style-updates-for-animated-sibling-elements-accelerated.html [ Failure ]
+
+webkit.org/b/233887 webanimations/custom-effect [ Failure ]

Added: trunk/LayoutTests/webanimations/custom-effect/custom-effect-expected.txt (0 => 286555)


--- trunk/LayoutTests/webanimations/custom-effect/custom-effect-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webanimations/custom-effect/custom-effect-expected.txt	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,7 @@
+
+PASS Custom effects with no fill do not fire with progress = 1.
+PASS Forward-filling custom effects fire once with progress = 1.
+PASS Backward-filling custom effects fire only once with progress = 0 during the before phase.
+PASS Custom effects are called when the associated animatoun is paused and seeked.
+PASS Custom effects fire callbacks with no other reason to update the page rendering.
+

Added: trunk/LayoutTests/webanimations/custom-effect/custom-effect.html (0 => 286555)


--- trunk/LayoutTests/webanimations/custom-effect/custom-effect.html	                        (rev 0)
+++ trunk/LayoutTests/webanimations/custom-effect/custom-effect.html	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,108 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CustomEffect</title>
+<script src=""
+<script src=""
+<script src=""
+<body>
+<script>
+'use strict';
+
+promise_test(async t => {
+    let numberOfCalls = 0;
+    let customEffectProgress = null;
+
+    const animation = document.timeline.animate(progress => {
+        customEffectProgress = progress;
+        numberOfCalls++;
+    }, { duration: 1 });
+
+    assert_equals(customEffectProgress, null, "Callback does not fire upon creation.");
+
+    await waitForAnimationFrames(1);
+    assert_equals(customEffectProgress, 0, "Callback is first fired with progress = 0.");
+
+    await animation.finished;
+    const numberOfCallsAfterEffectEnded = numberOfCalls;
+
+    await waitForAnimationFrames(1);
+    assert_equals(numberOfCallsAfterEffectEnded, numberOfCalls, "Callback is no longer fired after custom effect entered the after phase.");
+    assert_not_equals(customEffectProgress, 1, "Callback is first fired with progress = 1.");
+}, "Custom effects with no fill do not fire with progress = 1.");
+
+promise_test(async t => {
+    let numberOfCalls = 0;
+    let customEffectProgress = null;
+
+    const animation = document.timeline.animate(progress => {
+        customEffectProgress = progress;
+        numberOfCalls++;
+    }, { fill: "forwards", duration: 1});
+
+    assert_equals(customEffectProgress, null, "Callback does not fire upon creation.");
+
+    await animation.finished;
+    assert_equals(customEffectProgress, 1, "Callback is finally fired with progress = 1.");
+
+    const numberOfCallsAfterEffectEnded = numberOfCalls;
+
+    await waitForAnimationFrames(1);
+    assert_equals(numberOfCallsAfterEffectEnded, numberOfCalls, "Callback is no longer fired after custom effect entered the after phase.");
+}, "Forward-filling custom effects fire once with progress = 1.");
+
+promise_test(async t => {
+    let numberOfCalls = 0;
+    let customEffectProgress = null;
+
+    // Create an animation that won't start until long into the future.
+    const animation = new Animation;
+    animation.startTime = document.timeline.currentTime + (100 * 1000);
+    animation.effect = new CustomEffect(progress => {
+        customEffectProgress = progress;
+        numberOfCalls++;
+    }, { fill: "backwards", duration: 1});
+
+    assert_equals(customEffectProgress, null, "Callback does not fire upon creation.");
+
+    await waitForAnimationFrames(1);
+    assert_equals(customEffectProgress, 0, "Callback is first fired with progress = 0.");
+
+    await waitForAnimationFrames(1);
+    assert_equals(numberOfCalls, 1, "Callback is not fired after the first frame as it's still in the before phase and its progress hasn't changed.");
+}, "Backward-filling custom effects fire only once with progress = 0 during the before phase.");
+
+promise_test(async t => {
+    let numberOfCalls = 0;
+    let customEffectProgress = null;
+
+    const duration = 1000;
+    const animation = document.timeline.animate(progress => {
+        customEffectProgress = progress;
+        numberOfCalls++;
+    }, duration);
+
+    animation.pause();
+    assert_equals(customEffectProgress, null, "Callback does not fire upon creation.");
+
+    await waitForAnimationFrames(1);
+    assert_equals(customEffectProgress, 0, "Callback is first fired with progress = 0.");
+
+    await waitForAnimationFrames(1);
+    assert_equals(numberOfCalls, 1, "Callback is not called while animation is paused.");
+
+    animation.currentTime = animation.startTime + (duration * 0.2);
+    animation.currentTime = animation.startTime + (duration * 0.1);
+
+    await waitForAnimationFrames(1);
+    assert_equals(numberOfCalls, 2, "Callback is only called once if changing the current time several times between frames.");
+    assert_equals(customEffectProgress, 0.1, "Callback is called with the update progress when seeking the animation.");
+}, "Custom effects are called when the associated animatoun is paused and seeked.");
+
+promise_test(async t => {
+    await new Promise(resolve => {
+        document.timeline.animate(progress => resolve(), 100 * 1000);
+    });
+}, "Custom effects fire callbacks with no other reason to update the page rendering.");
+
+</script>
+</body>

Added: trunk/LayoutTests/webanimations/custom-effect/document-timeline-animate-expected.txt (0 => 286555)


--- trunk/LayoutTests/webanimations/custom-effect/document-timeline-animate-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webanimations/custom-effect/document-timeline-animate-expected.txt	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,3 @@
+
+PASS document.timeline.animate() allows to set the animation's id.
+

Added: trunk/LayoutTests/webanimations/custom-effect/document-timeline-animate.html (0 => 286555)


--- trunk/LayoutTests/webanimations/custom-effect/document-timeline-animate.html	                        (rev 0)
+++ trunk/LayoutTests/webanimations/custom-effect/document-timeline-animate.html	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,17 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CustomEffect</title>
+<script src=""
+<script src=""
+<body>
+<script>
+'use strict';
+
+test(t => {
+    const id = "custom-animation-id";
+    const animation = document.timeline.animate(progress => { }, { duration: 1, id });
+    assert_equals(animation.id, id);
+}, "document.timeline.animate() allows to set the animation's id.");
+
+</script>
+</body>

Modified: trunk/Source/WTF/ChangeLog (286554 => 286555)


--- trunk/Source/WTF/ChangeLog	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WTF/ChangeLog	2021-12-06 19:30:57 UTC (rev 286555)
@@ -1,3 +1,15 @@
+2021-12-06  Antoine Quint  <[email protected]>
+
+        [Web Animations] Add a way to run scripted animations
+        https://bugs.webkit.org/show_bug.cgi?id=233869
+        rdar://85983542
+
+        Reviewed by Dean Jackson.
+
+        Add a new experimental feature for the CustomEffect interface.
+
+        * Scripts/Preferences/WebPreferencesExperimental.yaml:
+
 2021-12-06  Jon Lee  <[email protected]>
 
         Update GPU Process feature flags

Modified: trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml (286554 => 286555)


--- trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WTF/Scripts/Preferences/WebPreferencesExperimental.yaml	2021-12-06 19:30:57 UTC (rev 286555)
@@ -1471,6 +1471,19 @@
     WebCore:
       default: false
 
+WebAnimationsCustomEffectsEnabled:
+  type: bool
+  humanReadableName: "Web Animations custom effects"
+  humanReadableDescription: "Support for the CustomEffect interface"
+  defaultValue:
+    WebKitLegacy:
+      default: false
+    WebKit:
+      "ENABLE(EXPERIMENTAL_FEATURES)" : true
+      default: false
+    WebCore:
+      default: false
+
 # FIXME: This is enabled when ENABLE(EXPERIMENTAL_FEATURES) is true in WebKit2. Perhaps we should consider using that for WebKitLegacy as well.
 WebAnimationsMutableTimelinesEnabled:
   type: bool

Modified: trunk/Source/WebCore/CMakeLists.txt (286554 => 286555)


--- trunk/Source/WebCore/CMakeLists.txt	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/CMakeLists.txt	2021-12-06 19:30:57 UTC (rev 286555)
@@ -679,7 +679,6 @@
     animation/Animatable.idl
     animation/AnimationEffect.idl
     animation/AnimationFrameProvider.idl
-    animation/EffectTiming.idl
     animation/AnimationPlaybackEvent.idl
     animation/AnimationPlaybackEventInit.idl
     animation/AnimationTimeline.idl
@@ -688,10 +687,14 @@
     animation/CompositeOperation.idl
     animation/CompositeOperationOrAuto.idl
     animation/ComputedEffectTiming.idl
+    animation/CustomAnimationOptions.idl
+    animation/CustomEffect.idl
+    animation/CustomEffectCallback.idl
     animation/Document+WebAnimations.idl
     animation/DocumentOrShadowRoot+WebAnimations.idl
     animation/DocumentTimeline.idl
     animation/DocumentTimelineOptions.idl
+    animation/EffectTiming.idl
     animation/FillMode.idl
     animation/GetAnimationsOptions.idl
     animation/GlobalEventHandlers+CSSAnimations.idl

Modified: trunk/Source/WebCore/ChangeLog (286554 => 286555)


--- trunk/Source/WebCore/ChangeLog	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/ChangeLog	2021-12-06 19:30:57 UTC (rev 286555)
@@ -1,3 +1,69 @@
+2021-12-06  Antoine Quint  <[email protected]>
+
+        [Web Animations] Add a way to run scripted animations
+        https://bugs.webkit.org/show_bug.cgi?id=233869
+        rdar://85983542
+
+        Reviewed by Dean Jackson.
+
+        Tests: webanimations/custom-effect/custom-effect.html
+               webanimations/custom-effect/document-timeline-animate.html
+
+        This patch adds two new Web-exposed features to allow authors to write callback-based animations
+        leveraging the full power of the Web Animations model.
+
+        First, we add a new AnimationEffect subclass which wraps a callback to be executed on every tick
+        of the associated animation's timeline: CustomEffect. It can be constructed by providing a JS function
+        as its first parameter, and either a number or a dictionary to provide timing properties for the effect.
+        This is similar to how KeyframeEffect will accept a keyframes object and then timing data. The callback
+        is provided the effect progress as its sole parameter. Web authors can use this new interface as follows:
+
+            const animation = new Animation;
+            animation.effect = new CustomEffect(progress => { … }, 1000);
+            animation.play();
+
+        Second, to make starting callback-based animations more straightforward and in a very similar fashion
+        to how keyframe animations can be initiated on an element using Element.animate(), we introduce a new
+        animate() method on DocumentTimeline, allowing the previous exmaple to be written as:
+
+            const animation = document.timeline.animate(progress => { … }, 1000);
+
+        This simple approach allows Web authors to move past the simple use of requestAnimationFrame() and harness
+        the Web Animations timing model which will let them pause and resume animations, seek them, control their
+        playback rate, apply easing, respond to the "finished" promise, etc.
+
+        The code itself is very simple, CustomEffect is simply an AnimationEffect subclass that indicates that it's
+        always interested in scheduling updates while active using the ticksContinouslyWhileActive() method. This
+        means that all the scheduling logic contained in WebAnimation and AnimationEffect applies, allowing callbacks
+        to not be fired when the animation is paused or when the page is suspended, or fired sparingly when a steps()
+        timing function is specified.
+
+        * CMakeLists.txt:
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * Headers.cmake:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * animation/AnimationEffect.h:
+        (WebCore::AnimationEffect::isCustomEffect const):
+        * animation/CustomAnimationOptions.h: Added.
+        * animation/CustomAnimationOptions.idl: Added.
+        * animation/CustomEffect.cpp: Added.
+        (WebCore::CustomEffect::create):
+        (WebCore::CustomEffect::CustomEffect):
+        (WebCore::CustomEffect::animationDidTick):
+        * animation/CustomEffect.h: Added.
+        (WebCore::CustomEffect::~CustomEffect):
+        * animation/CustomEffect.idl: Added.
+        * animation/CustomEffectCallback.h: Added.
+        * animation/CustomEffectCallback.idl: Added.
+        * animation/DocumentTimeline.cpp:
+        (WebCore::DocumentTimeline::animate):
+        * animation/DocumentTimeline.h:
+        * animation/DocumentTimeline.idl:
+        * bindings/js/WebCoreBuiltinNames.h:
+
 2021-12-06  Rob Buis  <[email protected]>
 
         Null check in shouldUseBreakElement

Modified: trunk/Source/WebCore/DerivedSources-input.xcfilelist (286554 => 286555)


--- trunk/Source/WebCore/DerivedSources-input.xcfilelist	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/DerivedSources-input.xcfilelist	2021-12-06 19:30:57 UTC (rev 286555)
@@ -814,6 +814,9 @@
 $(PROJECT_DIR)/animation/CompositeOperation.idl
 $(PROJECT_DIR)/animation/CompositeOperationOrAuto.idl
 $(PROJECT_DIR)/animation/ComputedEffectTiming.idl
+$(PROJECT_DIR)/animation/CustomAnimationOptions.idl
+$(PROJECT_DIR)/animation/CustomEffect.idl
+$(PROJECT_DIR)/animation/CustomEffectCallback.idl
 $(PROJECT_DIR)/animation/Document+WebAnimations.idl
 $(PROJECT_DIR)/animation/DocumentOrShadowRoot+WebAnimations.idl
 $(PROJECT_DIR)/animation/DocumentTimeline.idl

Modified: trunk/Source/WebCore/DerivedSources-output.xcfilelist (286554 => 286555)


--- trunk/Source/WebCore/DerivedSources-output.xcfilelist	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/DerivedSources-output.xcfilelist	2021-12-06 19:30:57 UTC (rev 286555)
@@ -530,6 +530,12 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCryptoRsaHashedKeyAlgorithm.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCryptoRsaKeyAlgorithm.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCryptoRsaKeyAlgorithm.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCustomAnimationOptions.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCustomAnimationOptions.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCustomEffect.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCustomEffect.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCustomEffectCallback.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCustomEffectCallback.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCustomElementRegistry.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCustomElementRegistry.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSCustomEvent.cpp

Modified: trunk/Source/WebCore/DerivedSources.make (286554 => 286555)


--- trunk/Source/WebCore/DerivedSources.make	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/DerivedSources.make	2021-12-06 19:30:57 UTC (rev 286555)
@@ -703,6 +703,9 @@
     $(WebCore)/animation/CompositeOperation.idl \
     $(WebCore)/animation/CompositeOperationOrAuto.idl \
     $(WebCore)/animation/ComputedEffectTiming.idl \
+    $(WebCore)/animation/CustomAnimationOptions.idl \
+    $(WebCore)/animation/CustomEffect.idl \
+    $(WebCore)/animation/CustomEffectCallback.idl \
     $(WebCore)/animation/Document+WebAnimations.idl \
     $(WebCore)/animation/DocumentOrShadowRoot+WebAnimations.idl \
     $(WebCore)/animation/DocumentTimeline.idl \

Modified: trunk/Source/WebCore/Headers.cmake (286554 => 286555)


--- trunk/Source/WebCore/Headers.cmake	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/Headers.cmake	2021-12-06 19:30:57 UTC (rev 286555)
@@ -384,6 +384,7 @@
     accessibility/isolatedtree/AXIsolatedTree.h
 
     animation/CSSPropertyBlendingClient.h
+    animation/CustomAnimationOptions.h
     animation/CompositeOperation.h
     animation/DocumentTimelinesController.h
     animation/EffectTiming.h

Modified: trunk/Source/WebCore/Sources.txt (286554 => 286555)


--- trunk/Source/WebCore/Sources.txt	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/Sources.txt	2021-12-06 19:30:57 UTC (rev 286555)
@@ -469,6 +469,7 @@
 animation/CSSAnimation.cpp
 animation/CSSPropertyAnimation.cpp
 animation/CSSTransition.cpp
+animation/CustomEffect.cpp
 animation/DeclarativeAnimation.cpp
 animation/DocumentTimeline.cpp
 animation/DocumentTimelinesController.cpp
@@ -3005,6 +3006,9 @@
 JSCryptoKeyUsage.cpp
 JSCryptoRsaHashedKeyAlgorithm.cpp
 JSCryptoRsaKeyAlgorithm.cpp
+JSCustomAnimationOptions.cpp
+JSCustomEffect.cpp
+JSCustomEffectCallback.cpp
 JSCustomElementRegistry.cpp
 JSCustomEvent.cpp
 JSDOMApplicationCache.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (286554 => 286555)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-12-06 19:30:57 UTC (rev 286555)
@@ -2279,6 +2279,9 @@
 		715AD7212050513F00D592DC /* CSSTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 7123C186204739BA00789392 /* CSSTransition.h */; };
 		71729F7B20F3BA4900801CE6 /* DocumentTimelineOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71729F7A20F3BA3A00801CE6 /* DocumentTimelineOptions.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		71729F7E20F3BB4700801CE6 /* JSDocumentTimelineOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71729F7C20F3BAB900801CE6 /* JSDocumentTimelineOptions.h */; };
+		7173694A275E0B5E003ADA9B /* CustomEffect.h in Headers */ = {isa = PBXBuildFile; fileRef = 71A74B082759293600DE80BA /* CustomEffect.h */; };
+		7173694B275E0B6A003ADA9B /* CustomEffectCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 71A74B0A27592B3500DE80BA /* CustomEffectCallback.h */; };
+		7173694C275E0BAB003ADA9B /* CustomAnimationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71736947275E0B4B003ADA9B /* CustomAnimationOptions.h */; };
 		7177AD57274295D1002F103B /* HTMLModelElementCamera.h in Headers */ = {isa = PBXBuildFile; fileRef = 7177AD5627429590002F103B /* HTMLModelElementCamera.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7181A16C244F0F40007D8A24 /* DocumentTimelinesController.h in Headers */ = {isa = PBXBuildFile; fileRef = 7181A169244F0F2C007D8A24 /* DocumentTimelinesController.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		71A1B6081DEE5AD70073BCFB /* modern-media-controls-localized-strings.js in Resources */ = {isa = PBXBuildFile; fileRef = 71A1B6061DEE5A820073BCFB /* modern-media-controls-localized-strings.js */; };
@@ -11076,6 +11079,8 @@
 		71729F7A20F3BA3A00801CE6 /* DocumentTimelineOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DocumentTimelineOptions.h; sourceTree = "<group>"; };
 		71729F7C20F3BAB900801CE6 /* JSDocumentTimelineOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDocumentTimelineOptions.h; sourceTree = "<group>"; };
 		71729F7D20F3BABA00801CE6 /* JSDocumentTimelineOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDocumentTimelineOptions.cpp; sourceTree = "<group>"; };
+		71736947275E0B4B003ADA9B /* CustomAnimationOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomAnimationOptions.h; sourceTree = "<group>"; };
+		71736949275E0B4C003ADA9B /* CustomAnimationOptions.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CustomAnimationOptions.idl; sourceTree = "<group>"; };
 		7173DEBD2614DF040097DF32 /* Styleable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Styleable.cpp; sourceTree = "<group>"; };
 		7177AD542742952F002F103B /* HTMLModelElementCamera.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLModelElementCamera.idl; sourceTree = "<group>"; };
 		7177AD5627429590002F103B /* HTMLModelElementCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLModelElementCamera.h; sourceTree = "<group>"; };
@@ -11112,6 +11117,11 @@
 		71A57DF0154BE25C0009D120 /* SVGPathUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGPathUtilities.h; sourceTree = "<group>"; };
 		71A58193236F466400D81A24 /* KeyframeEffectStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyframeEffectStack.h; sourceTree = "<group>"; };
 		71A58195236F466500D81A24 /* KeyframeEffectStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyframeEffectStack.cpp; sourceTree = "<group>"; };
+		71A74B052759293600DE80BA /* CustomEffect.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CustomEffect.idl; sourceTree = "<group>"; };
+		71A74B072759293600DE80BA /* CustomEffect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CustomEffect.cpp; sourceTree = "<group>"; };
+		71A74B082759293600DE80BA /* CustomEffect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomEffect.h; sourceTree = "<group>"; };
+		71A74B0927592A5300DE80BA /* CustomEffectCallback.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CustomEffectCallback.idl; sourceTree = "<group>"; };
+		71A74B0A27592B3500DE80BA /* CustomEffectCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomEffectCallback.h; sourceTree = "<group>"; };
 		71AEE4EB21B5A49C00DDB036 /* TouchAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TouchAction.h; sourceTree = "<group>"; };
 		71B0460A1DD3C2EE00EE19CF /* status-support.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = "status-support.js"; sourceTree = "<group>"; };
 		71B28424203CEC0B0036AA5D /* JSCSSAnimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCSSAnimation.cpp; sourceTree = "<group>"; };
@@ -24257,6 +24267,13 @@
 				7123C187204739BB00789392 /* CSSTransition.cpp */,
 				7123C186204739BA00789392 /* CSSTransition.h */,
 				7123C185204739B900789392 /* CSSTransition.idl */,
+				71736947275E0B4B003ADA9B /* CustomAnimationOptions.h */,
+				71736949275E0B4C003ADA9B /* CustomAnimationOptions.idl */,
+				71A74B072759293600DE80BA /* CustomEffect.cpp */,
+				71A74B082759293600DE80BA /* CustomEffect.h */,
+				71A74B052759293600DE80BA /* CustomEffect.idl */,
+				71A74B0A27592B3500DE80BA /* CustomEffectCallback.h */,
+				71A74B0927592A5300DE80BA /* CustomEffectCallback.idl */,
 				715AD71F2050512400D592DC /* DeclarativeAnimation.cpp */,
 				715AD71D2050512400D592DC /* DeclarativeAnimation.h */,
 				7C3A8AC02509A602008C477F /* Document+WebAnimations.idl */,
@@ -33808,6 +33825,9 @@
 				93F1992F08245E59001E9ABC /* Cursor.h in Headers */,
 				BC2272A20E82E87C00E7F975 /* CursorData.h in Headers */,
 				BC2272AD0E82E8F300E7F975 /* CursorList.h in Headers */,
+				7173694C275E0BAB003ADA9B /* CustomAnimationOptions.h in Headers */,
+				7173694A275E0B5E003ADA9B /* CustomEffect.h in Headers */,
+				7173694B275E0B6A003ADA9B /* CustomEffectCallback.h in Headers */,
 				93D437A01D57B19A00AB85EA /* CustomElementReactionQueue.h in Headers */,
 				9BD4E91B1C462CFC005065BC /* CustomElementRegistry.h in Headers */,
 				62CD325A1157E57C0063B0A7 /* CustomEvent.h in Headers */,

Modified: trunk/Source/WebCore/animation/AnimationEffect.h (286554 => 286555)


--- trunk/Source/WebCore/animation/AnimationEffect.h	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/animation/AnimationEffect.h	2021-12-06 19:30:57 UTC (rev 286555)
@@ -51,6 +51,7 @@
 public:
     virtual ~AnimationEffect();
 
+    virtual bool isCustomEffect() const { return false; }
     virtual bool isKeyframeEffect() const { return false; }
 
     EffectTiming getBindingsTiming() const;

Copied: trunk/Source/WebCore/animation/CustomAnimationOptions.h (from rev 286554, trunk/Source/WebCore/animation/DocumentTimeline.idl) (0 => 286555)


--- trunk/Source/WebCore/animation/CustomAnimationOptions.h	                        (rev 0)
+++ trunk/Source/WebCore/animation/CustomAnimationOptions.h	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "EffectTiming.h"
+
+namespace WebCore {
+
+struct CustomAnimationOptions : EffectTiming {
+    String id;
+};
+
+} // namespace WebCore
+

Copied: trunk/Source/WebCore/animation/CustomAnimationOptions.idl (from rev 286554, trunk/Source/WebCore/animation/DocumentTimeline.idl) (0 => 286555)


--- trunk/Source/WebCore/animation/CustomAnimationOptions.idl	                        (rev 0)
+++ trunk/Source/WebCore/animation/CustomAnimationOptions.idl	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+dictionary CustomAnimationOptions : EffectTiming {
+    DOMString id = "";
+};
+

Added: trunk/Source/WebCore/animation/CustomEffect.cpp (0 => 286555)


--- trunk/Source/WebCore/animation/CustomEffect.cpp	                        (rev 0)
+++ trunk/Source/WebCore/animation/CustomEffect.cpp	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CustomEffect.h"
+
+#include "CustomEffectCallback.h"
+#include <_javascript_Core/Exception.h>
+
+namespace WebCore {
+using namespace JSC;
+
+ExceptionOr<Ref<CustomEffect>> CustomEffect::create(Ref<CustomEffectCallback>&& callback, std::optional<std::variant<double, EffectTiming>>&& options)
+{
+    auto customEffect = adoptRef(*new CustomEffect(WTFMove(callback)));
+
+    if (options) {
+        OptionalEffectTiming timing;
+        auto optionsValue = options.value();
+        if (std::holds_alternative<double>(optionsValue)) {
+            std::variant<double, String> duration = std::get<double>(optionsValue);
+            timing.duration = duration;
+        } else {
+            auto effectTimingOptions = std::get<EffectTiming>(optionsValue);
+
+            timing = {
+                effectTimingOptions.duration,
+                effectTimingOptions.iterations,
+                effectTimingOptions.delay,
+                effectTimingOptions.endDelay,
+                effectTimingOptions.iterationStart,
+                effectTimingOptions.easing,
+                effectTimingOptions.fill,
+                effectTimingOptions.direction
+            };
+        }
+        auto updateTimingResult = customEffect->updateTiming(timing);
+        if (updateTimingResult.hasException())
+            return updateTimingResult.releaseException();
+    }
+
+    return customEffect;
+}
+
+CustomEffect::CustomEffect(Ref<CustomEffectCallback>&& callback)
+    : m_callback(WTFMove(callback))
+{
+}
+
+void CustomEffect::animationDidTick()
+{
+    auto computedTiming = getComputedTiming();
+    if (!computedTiming.progress)
+        return;
+
+    m_callback->handleEvent(*computedTiming.progress);
+}
+
+} // namespace WebCore

Copied: trunk/Source/WebCore/animation/CustomEffect.h (from rev 286554, trunk/Source/WebCore/animation/DocumentTimeline.idl) (0 => 286555)


--- trunk/Source/WebCore/animation/CustomEffect.h	                        (rev 0)
+++ trunk/Source/WebCore/animation/CustomEffect.h	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "AnimationEffect.h"
+#include "CustomEffectCallback.h"
+#include "EffectTiming.h"
+#include <wtf/Ref.h>
+
+namespace WebCore {
+
+class CustomEffect : public AnimationEffect {
+public:
+    static ExceptionOr<Ref<CustomEffect>> create(Ref<CustomEffectCallback>&&, std::optional<std::variant<double, EffectTiming>>&&);
+    ~CustomEffect() { }
+
+private:
+    CustomEffect(Ref<CustomEffectCallback>&&);
+
+    // AnimationEffect
+    bool isCustomEffect() const final { return true; }
+    void animationDidTick() final;
+    bool ticksContinouslyWhileActive() const final { return true; }
+
+    Ref<CustomEffectCallback> m_callback;
+};
+
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_ANIMATION_EFFECT(CustomEffect, isCustomEffect());

Copied: trunk/Source/WebCore/animation/CustomEffect.idl (from rev 286554, trunk/Source/WebCore/animation/DocumentTimeline.idl) (0 => 286555)


--- trunk/Source/WebCore/animation/CustomEffect.idl	                        (rev 0)
+++ trunk/Source/WebCore/animation/CustomEffect.idl	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    EnabledBySetting=WebAnimationsCustomEffectsEnabled,
+    Exposed=Window,
+    JSGenerateToNativeObject,
+] interface CustomEffect : AnimationEffect {
+    constructor(CustomEffectCallback callback, optional (unrestricted double or EffectTiming) options);
+};

Copied: trunk/Source/WebCore/animation/CustomEffectCallback.h (from rev 286554, trunk/Source/WebCore/animation/DocumentTimeline.idl) (0 => 286555)


--- trunk/Source/WebCore/animation/CustomEffectCallback.h	                        (rev 0)
+++ trunk/Source/WebCore/animation/CustomEffectCallback.h	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ActiveDOMCallback.h"
+#include "CallbackResult.h"
+#include <wtf/RefCounted.h>
+#include <wtf/Seconds.h>
+
+namespace WebCore {
+
+class CustomEffectCallback : public RefCounted<CustomEffectCallback>, public ActiveDOMCallback {
+public:
+    using ActiveDOMCallback::ActiveDOMCallback;
+
+    virtual CallbackResult<void> handleEvent(double progress) = 0;
+};
+
+} // namespace WebCore

Copied: trunk/Source/WebCore/animation/CustomEffectCallback.idl (from rev 286554, trunk/Source/WebCore/animation/DocumentTimeline.idl) (0 => 286555)


--- trunk/Source/WebCore/animation/CustomEffectCallback.idl	                        (rev 0)
+++ trunk/Source/WebCore/animation/CustomEffectCallback.idl	2021-12-06 19:30:57 UTC (rev 286555)
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+callback CustomEffectCallback = undefined (double progress);

Modified: trunk/Source/WebCore/animation/DocumentTimeline.cpp (286554 => 286555)


--- trunk/Source/WebCore/animation/DocumentTimeline.cpp	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/animation/DocumentTimeline.cpp	2021-12-06 19:30:57 UTC (rev 286555)
@@ -28,6 +28,9 @@
 
 #include "AnimationEventBase.h"
 #include "CSSTransition.h"
+#include "CustomAnimationOptions.h"
+#include "CustomEffect.h"
+#include "CustomEffectCallback.h"
 #include "DeclarativeAnimation.h"
 #include "Document.h"
 #include "DocumentTimelinesController.h"
@@ -494,4 +497,37 @@
     return m_numberOfAnimationTimelineInvalidationsForTesting;
 }
 
+ExceptionOr<Ref<WebAnimation>> DocumentTimeline::animate(Ref<CustomEffectCallback>&& callback, std::optional<std::variant<double, CustomAnimationOptions>>&& options)
+{
+    ASSERT(m_document);
+
+    String id = "";
+    std::optional<std::variant<double, EffectTiming>> customEffectOptions;
+
+    if (options) {
+        std::variant<double, EffectTiming> customEffectOptionsVariant;
+        if (std::holds_alternative<double>(*options))
+            customEffectOptionsVariant = std::get<double>(*options);
+        else {
+            auto customEffectOptions = std::get<CustomAnimationOptions>(*options);
+            id = customEffectOptions.id;
+            customEffectOptionsVariant = WTFMove(customEffectOptions);
+        }
+        customEffectOptions = customEffectOptionsVariant;
+    }
+
+    auto customEffectResult = CustomEffect::create(WTFMove(callback), WTFMove(customEffectOptions));
+    if (customEffectResult.hasException())
+        return customEffectResult.releaseException();
+
+    auto animation = WebAnimation::create(*document(), &customEffectResult.returnValue().get());
+    animation->setId(id);
+
+    auto animationPlayResult = animation->play();
+    if (animationPlayResult.hasException())
+        return animationPlayResult.releaseException();
+
+    return animation;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/animation/DocumentTimeline.h (286554 => 286555)


--- trunk/Source/WebCore/animation/DocumentTimeline.h	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/animation/DocumentTimeline.h	2021-12-06 19:30:57 UTC (rev 286555)
@@ -34,10 +34,13 @@
 namespace WebCore {
 
 class AnimationEventBase;
+class CustomEffectCallback;
 class DocumentTimelinesController;
 class RenderBoxModelObject;
 class RenderElement;
 
+struct CustomAnimationOptions;
+
 class DocumentTimeline final : public AnimationTimeline
 {
 public:
@@ -50,6 +53,7 @@
     Document* document() const { return m_document.get(); }
 
     std::optional<Seconds> currentTime() override;
+    ExceptionOr<Ref<WebAnimation>> animate(Ref<CustomEffectCallback>&&, std::optional<std::variant<double, CustomAnimationOptions>>&&);
 
     void animationTimingDidChange(WebAnimation&) override;
     void removeAnimation(WebAnimation&) override;

Modified: trunk/Source/WebCore/animation/DocumentTimeline.idl (286554 => 286555)


--- trunk/Source/WebCore/animation/DocumentTimeline.idl	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/animation/DocumentTimeline.idl	2021-12-06 19:30:57 UTC (rev 286555)
@@ -27,4 +27,5 @@
     Exposed=Window
 ] interface DocumentTimeline : AnimationTimeline {
     [CallWith=Document] constructor(optional DocumentTimelineOptions options);
+    [EnabledBySetting=WebAnimationsCustomEffectsEnabled] WebAnimation animate(CustomEffectCallback callback, optional (unrestricted double or CustomAnimationOptions) options);
 };

Modified: trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h (286554 => 286555)


--- trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h	2021-12-06 19:22:54 UTC (rev 286554)
+++ trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h	2021-12-06 19:30:57 UTC (rev 286555)
@@ -106,6 +106,7 @@
     macro(CSSUnparsedValue) \
     macro(CSSVariableReferenceValue) \
     macro(CustomElementRegistry) \
+    macro(CustomEffect) \
     macro(Database) \
     macro(DataTransferItem) \
     macro(DataTransferItemList) \
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to