mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 04:12:43 +00:00 
			
		
		
		
	LibWeb: Set KeyframeEffect's pseudo-element if applicable
This commit is contained in:
		
							parent
							
								
									921f6c1e78
								
							
						
					
					
						commit
						2ee022dead
					
				
					 3 changed files with 40 additions and 13 deletions
				
			
		|  | @ -630,7 +630,7 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<KeyframeEffect>> KeyframeEffect::construct_ | ||||||
|         // When assigning this property, the error-handling defined for the pseudoElement setter on the interface is
 |         // When assigning this property, the error-handling defined for the pseudoElement setter on the interface is
 | ||||||
|         // applied. If the setter requires an exception to be thrown, this procedure must throw the same exception and
 |         // applied. If the setter requires an exception to be thrown, this procedure must throw the same exception and
 | ||||||
|         // abort all further steps.
 |         // abort all further steps.
 | ||||||
|         effect->set_pseudo_element(options.get<KeyframeEffectOptions>().pseudo_element); |         TRY(effect->set_pseudo_element(options.get<KeyframeEffectOptions>().pseudo_element)); | ||||||
|     } |     } | ||||||
|     //     Otherwise,
 |     //     Otherwise,
 | ||||||
|     else { |     else { | ||||||
|  | @ -730,16 +730,14 @@ void KeyframeEffect::set_target(DOM::Element* target) | ||||||
|         m_target_element->associate_with_effect(*this); |         m_target_element->associate_with_effect(*this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void KeyframeEffect::set_pseudo_element(Optional<String> pseudo_element) | WebIDL::ExceptionOr<void> KeyframeEffect::set_pseudo_element(Optional<String> pseudo_element) | ||||||
| { | { | ||||||
|  |     auto& realm = this->realm(); | ||||||
|  | 
 | ||||||
|     // On setting, sets the target pseudo-selector of the animation effect to the provided value after applying the
 |     // On setting, sets the target pseudo-selector of the animation effect to the provided value after applying the
 | ||||||
|     // following exceptions:
 |     // following exceptions:
 | ||||||
| 
 | 
 | ||||||
|     // FIXME:
 |     // FIXME:
 | ||||||
|     // - If the provided value is not null and is an invalid <pseudo-element-selector>, the user agent must throw a
 |  | ||||||
|     //   DOMException with error name SyntaxError and leave the target pseudo-selector of this animation effect
 |  | ||||||
|     //   unchanged.
 |  | ||||||
| 
 |  | ||||||
|     // - If one of the legacy Selectors Level 2 single-colon selectors (':before', ':after', ':first-letter', or
 |     // - If one of the legacy Selectors Level 2 single-colon selectors (':before', ':after', ':first-letter', or
 | ||||||
|     //   ':first-line') is specified, the target pseudo-selector must be set to the equivalent two-colon selector
 |     //   ':first-line') is specified, the target pseudo-selector must be set to the equivalent two-colon selector
 | ||||||
|     //   (e.g. '::before').
 |     //   (e.g. '::before').
 | ||||||
|  | @ -747,12 +745,33 @@ void KeyframeEffect::set_pseudo_element(Optional<String> pseudo_element) | ||||||
|         auto value = pseudo_element.value(); |         auto value = pseudo_element.value(); | ||||||
| 
 | 
 | ||||||
|         if (value == ":before" || value == ":after" || value == ":first-letter" || value == ":first-line") { |         if (value == ":before" || value == ":after" || value == ":first-letter" || value == ":first-line") { | ||||||
|             m_target_pseudo_selector = MUST(String::formatted(":{}", value)); |             m_target_pseudo_selector = CSS::Selector::PseudoElement::from_string(MUST(value.substring_from_byte_offset(1))); | ||||||
|             return; |             return {}; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     m_target_pseudo_selector = pseudo_element; |     // - If the provided value is not null and is an invalid <pseudo-element-selector>, the user agent must throw a
 | ||||||
|  |     //   DOMException with error name SyntaxError and leave the target pseudo-selector of this animation effect
 | ||||||
|  |     //   unchanged.
 | ||||||
|  |     if (pseudo_element.has_value()) { | ||||||
|  |         auto pseudo_element_without_colons = MUST(pseudo_element->replace("::"sv, ""sv, ReplaceMode::FirstOnly)); | ||||||
|  |         if (auto value = CSS::Selector::PseudoElement::from_string(pseudo_element_without_colons); value.has_value()) { | ||||||
|  |             m_target_pseudo_selector = value; | ||||||
|  |         } else { | ||||||
|  |             return WebIDL::SyntaxError::create(realm, MUST(String::formatted("Invalid pseudo-element selector: \"{}\"", pseudo_element.value()))); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         m_target_pseudo_selector = {}; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return {}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Optional<CSS::Selector::PseudoElement::Type> KeyframeEffect::pseudo_element_type() const | ||||||
|  | { | ||||||
|  |     if (!m_target_pseudo_selector.has_value()) | ||||||
|  |         return {}; | ||||||
|  |     return m_target_pseudo_selector->type(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-getkeyframes
 | // https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-getkeyframes
 | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ | ||||||
| #include <LibWeb/Bindings/KeyframeEffectPrototype.h> | #include <LibWeb/Bindings/KeyframeEffectPrototype.h> | ||||||
| #include <LibWeb/Bindings/PlatformObject.h> | #include <LibWeb/Bindings/PlatformObject.h> | ||||||
| #include <LibWeb/CSS/PropertyID.h> | #include <LibWeb/CSS/PropertyID.h> | ||||||
|  | #include <LibWeb/CSS/Selector.h> | ||||||
| #include <LibWeb/CSS/StyleValue.h> | #include <LibWeb/CSS/StyleValue.h> | ||||||
| 
 | 
 | ||||||
| namespace Web::Animations { | namespace Web::Animations { | ||||||
|  | @ -84,8 +85,12 @@ public: | ||||||
|     DOM::Element* target() const override { return m_target_element; } |     DOM::Element* target() const override { return m_target_element; } | ||||||
|     void set_target(DOM::Element* target); |     void set_target(DOM::Element* target); | ||||||
| 
 | 
 | ||||||
|     Optional<String> pseudo_element() const { return m_target_pseudo_selector; } |     // JS bindings
 | ||||||
|     void set_pseudo_element(Optional<String>); |     Optional<StringView> pseudo_element() const { return m_target_pseudo_selector->name(); } | ||||||
|  |     WebIDL::ExceptionOr<void> set_pseudo_element(Optional<String>); | ||||||
|  | 
 | ||||||
|  |     Optional<CSS::Selector::PseudoElement::Type> pseudo_element_type() const; | ||||||
|  |     void set_pseudo_element(Optional<CSS::Selector::PseudoElement> pseudo_element) { m_target_pseudo_selector = pseudo_element; } | ||||||
| 
 | 
 | ||||||
|     Bindings::CompositeOperation composite() const { return m_composite; } |     Bindings::CompositeOperation composite() const { return m_composite; } | ||||||
|     void set_composite(Bindings::CompositeOperation value) { m_composite = value; } |     void set_composite(Bindings::CompositeOperation value) { m_composite = value; } | ||||||
|  | @ -109,7 +114,7 @@ private: | ||||||
|     JS::GCPtr<DOM::Element> m_target_element {}; |     JS::GCPtr<DOM::Element> m_target_element {}; | ||||||
| 
 | 
 | ||||||
|     // https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-pseudoelement
 |     // https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-pseudoelement
 | ||||||
|     Optional<String> m_target_pseudo_selector {}; |     Optional<CSS::Selector::PseudoElement> m_target_pseudo_selector {}; | ||||||
| 
 | 
 | ||||||
|     // https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-composite
 |     // https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-composite
 | ||||||
|     Bindings::CompositeOperation m_composite { Bindings::CompositeOperation::Replace }; |     Bindings::CompositeOperation m_composite { Bindings::CompositeOperation::Replace }; | ||||||
|  |  | ||||||
|  | @ -1074,6 +1074,8 @@ ErrorOr<void> StyleComputer::compute_cascaded_values(StyleProperties& style, DOM | ||||||
|             effect->set_timing_function(move(timing_function)); |             effect->set_timing_function(move(timing_function)); | ||||||
|             effect->set_fill_mode(Animations::css_fill_mode_to_bindings_fill_mode(fill_mode)); |             effect->set_fill_mode(Animations::css_fill_mode_to_bindings_fill_mode(fill_mode)); | ||||||
|             effect->set_playback_direction(Animations::css_animation_direction_to_bindings_playback_direction(direction)); |             effect->set_playback_direction(Animations::css_animation_direction_to_bindings_playback_direction(direction)); | ||||||
|  |             if (pseudo_element.has_value()) | ||||||
|  |                 effect->set_pseudo_element(Selector::PseudoElement { pseudo_element.value() }); | ||||||
| 
 | 
 | ||||||
|             auto animation = CSSAnimation::create(realm); |             auto animation = CSSAnimation::create(realm); | ||||||
|             animation->set_id(animation_name.release_value()); |             animation->set_id(animation_name.release_value()); | ||||||
|  | @ -1099,7 +1101,8 @@ ErrorOr<void> StyleComputer::compute_cascaded_values(StyleProperties& style, DOM | ||||||
| 
 | 
 | ||||||
|         if (auto effect = animation->effect(); effect && effect->is_keyframe_effect()) { |         if (auto effect = animation->effect(); effect && effect->is_keyframe_effect()) { | ||||||
|             auto& keyframe_effect = *static_cast<Animations::KeyframeEffect*>(effect.ptr()); |             auto& keyframe_effect = *static_cast<Animations::KeyframeEffect*>(effect.ptr()); | ||||||
|             TRY(collect_animation_into(keyframe_effect, style)); |             if (keyframe_effect.pseudo_element_type() == pseudo_element) | ||||||
|  |                 TRY(collect_animation_into(keyframe_effect, style)); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Matthew Olsson
						Matthew Olsson