From 086c044dc34dfc0f74fbe41f4ecb402b2cd34884 Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel.baumann@progress-linux.org>
Date: Fri, 19 Apr 2024 03:13:33 +0200
Subject: Merging upstream version 125.0.1.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
---
 servo/ports/geckolib/Cargo.toml    |   1 +
 servo/ports/geckolib/cbindgen.toml |  13 ++-
 servo/ports/geckolib/glue.rs       | 210 ++++++++++++++++++++++++++++++-------
 servo/ports/geckolib/lib.rs        |   1 +
 4 files changed, 183 insertions(+), 42 deletions(-)

(limited to 'servo/ports/geckolib')

diff --git a/servo/ports/geckolib/Cargo.toml b/servo/ports/geckolib/Cargo.toml
index ebf4178014..1bdaaa80b7 100644
--- a/servo/ports/geckolib/Cargo.toml
+++ b/servo/ports/geckolib/Cargo.toml
@@ -31,3 +31,4 @@ style = {path = "../../components/style", features = ["gecko"]}
 style_traits = {path = "../../components/style_traits"}
 thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
 to_shmem = {path = "../../components/to_shmem"}
+lazy_static = "1.0"
diff --git a/servo/ports/geckolib/cbindgen.toml b/servo/ports/geckolib/cbindgen.toml
index b703dc6c92..8e6818e421 100644
--- a/servo/ports/geckolib/cbindgen.toml
+++ b/servo/ports/geckolib/cbindgen.toml
@@ -140,6 +140,7 @@ include = [
   "ScrollSnapStrictness",
   "ScrollSnapType",
   "ScrollTimelineName",
+  "TransitionBehavior",
   "ViewTimelineInset",
   "OverflowAnchor",
   "OverflowClipBox",
@@ -365,9 +366,7 @@ renaming_overrides_prefixing = true
 
 "CalcLengthPercentage" = """
   inline CSSCoord ResolveToCSSPixels(CSSCoord aBasis) const;
-
-  using CoordRounder = nscoord(*)(float);
-  nscoord Resolve(nscoord aBasis, CoordRounder) const;
+  inline nscoord Resolve(nscoord aBasis) const;
 """
 
 "GenericCalcNode" = """
@@ -428,10 +427,10 @@ renaming_overrides_prefixing = true
   inline bool IsDefinitelyZero() const;
   inline CSSCoord ResolveToCSSPixels(CSSCoord aPercentageBasisInCSSPixels) const;
   template<typename T> inline CSSCoord ResolveToCSSPixelsWith(T aPercentageGetter) const;
-  template<typename T, typename U>
-  inline nscoord Resolve(T aPercentageGetter, U aRoundingFunction) const;
-  template<typename T>
-  inline nscoord Resolve(nscoord aPercentageBasis, T aRoundingFunction) const;
+  template<typename T, typename PercentRounder>
+  inline nscoord Resolve(T aPercentageGetter, PercentRounder) const;
+  template<typename PercentRounder>
+  inline nscoord Resolve(nscoord aPercentageBasis, PercentRounder) const;
   template<typename T> inline nscoord Resolve(T aPercentageGetter) const;
   inline nscoord Resolve(nscoord aPercentageBasis) const;
 """
diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs
index a6c4ef1262..83c55ad9e0 100644
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -6,7 +6,7 @@ use super::error_reporter::ErrorReporter;
 use super::stylesheet_loader::{AsyncStylesheetParser, StylesheetLoader};
 use bincode::{deserialize, serialize};
 use cssparser::ToCss as ParserToCss;
-use cssparser::{Parser, ParserInput, SourceLocation, UnicodeRange};
+use cssparser::{BasicParseError, ParseError as CssParseError, Parser, ParserInput, SourceLocation, UnicodeRange, Token};
 use dom::{DocumentState, ElementState};
 use malloc_size_of::MallocSizeOfOps;
 use nsstring::{nsCString, nsString};
@@ -14,7 +14,6 @@ use selectors::matching::{ElementSelectorFlags, MatchingForInvalidation, Selecto
 use selectors::{Element, OpaqueElement};
 use servo_arc::{Arc, ArcBorrow};
 use smallvec::SmallVec;
-use style::custom_properties::DeferFontRelativeCustomPropertyResolution;
 use std::collections::BTreeSet;
 use std::fmt::Write;
 use std::iter;
@@ -26,6 +25,7 @@ use style::computed_value_flags::ComputedValueFlags;
 use style::context::ThreadLocalStyleContext;
 use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
 use style::counter_style;
+use style::custom_properties::DeferFontRelativeCustomPropertyResolution;
 use style::data::{self, ElementStyles};
 use style::dom::{ShowSubtreeData, TDocument, TElement, TNode};
 use style::driver;
@@ -204,6 +204,9 @@ pub unsafe extern "C" fn Servo_Initialize(
     // Pretend that we're a Servo Layout thread, to make some assertions happy.
     thread_state::initialize(thread_state::ThreadState::LAYOUT);
 
+    debug_assert!(is_main_thread());
+    lazy_static::initialize(&STYLE_THREAD_POOL);
+
     // Perform some debug-only runtime assertions.
     origin_flags::assert_flags_match();
     traversal_flags::assert_traversal_flags_match();
@@ -1204,8 +1207,16 @@ pub struct ShouldTransitionResult {
 }
 
 #[inline]
-fn is_transitionable(prop: PropertyDeclarationId) -> bool {
-    prop.is_animatable() && !prop.is_discrete_animatable()
+fn is_transitionable(prop: PropertyDeclarationId, behavior: computed::TransitionBehavior) -> bool {
+    if !prop.is_animatable() {
+        return false;
+    }
+
+    match behavior {
+        computed::TransitionBehavior::Normal => !prop.is_discrete_animatable(),
+        // If transition-behavior is allow-discrete, transitionable is the same as animatable.
+        computed::TransitionBehavior::AllowDiscrete => true,
+    }
 }
 
 #[no_mangle]
@@ -1213,6 +1224,7 @@ pub extern "C" fn Servo_ComputedValues_ShouldTransition(
     old: &ComputedValues,
     new: &ComputedValues,
     prop: &structs::AnimatedPropertyID,
+    behavior: computed::TransitionBehavior,
     old_transition_value: Option<&AnimationValue>,
     start: &mut structs::RefPtr<AnimationValue>,
     end: &mut structs::RefPtr<AnimationValue>,
@@ -1221,7 +1233,7 @@ pub extern "C" fn Servo_ComputedValues_ShouldTransition(
         return Default::default();
     };
     let prop = prop.as_borrowed();
-    if !is_transitionable(prop) {
+    if !is_transitionable(prop, behavior) {
         return Default::default();
     }
 
@@ -1241,7 +1253,10 @@ pub extern "C" fn Servo_ComputedValues_ShouldTransition(
     let Some(old_value) = AnimationValue::from_computed_values(prop, old) else {
         return Default::default();
     };
-    if old_value == new_value || !old_value.interpolable_with(&new_value) {
+    if old_value == new_value
+        || (matches!(behavior, computed::TransitionBehavior::Normal)
+            && !old_value.interpolable_with(&new_value))
+    {
         return Default::default();
     }
 
@@ -1263,8 +1278,9 @@ pub extern "C" fn Servo_ComputedValues_TransitionValueMatches(
     let Some(prop) = OwnedPropertyDeclarationId::from_gecko_animated_property_id(prop) else {
         return false;
     };
+    // Note: the running transitions should be transitionable, so it is always allow-discrete.
     let prop = prop.as_borrowed();
-    if !is_transitionable(prop) {
+    if !is_transitionable(prop, computed::TransitionBehavior::AllowDiscrete) {
         return false;
     }
     let Some(value) = AnimationValue::from_computed_values(prop, style) else {
@@ -1366,7 +1382,9 @@ pub unsafe extern "C" fn Servo_Property_IsInherited(
     let longhand_id = match prop_id {
         PropertyId::Custom(property_name) => {
             let stylist = &per_doc_data.borrow().stylist;
-            return stylist.get_custom_property_registration(&property_name).inherits()
+            return stylist
+                .get_custom_property_registration(&property_name)
+                .inherits();
         },
         PropertyId::NonCustom(id) => match id.longhand_or_shorthand() {
             Ok(lh) => lh,
@@ -6156,9 +6174,9 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(
     raw_data: &PerDocumentStyleData,
     computed_keyframes: &mut nsTArray<structs::ComputedKeyframeValues>,
 ) {
-    use style::properties::PropertyDeclaration;
-    use style::custom_properties::CustomPropertiesBuilder;
     use style::applicable_declarations::CascadePriority;
+    use style::custom_properties::CustomPropertiesBuilder;
+    use style::properties::PropertyDeclaration;
     let data = raw_data.borrow();
     let element = GeckoElement(element);
     let pseudo = PseudoElement::from_pseudo_type(pseudo_type, None);
@@ -6197,8 +6215,8 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(
         let mut seen = PropertyDeclarationIdSet::default();
         let mut iter = PrioritizedPropertyIter::new(&keyframe.mPropertyValues);
 
-        // FIXME: This is pretty much a hack. Instead, the AnimatedValue should be better
-        // integrated in the cascade. This would allow us to fix revert() too.
+        // FIXME (bug 1883255): This is pretty much a hack. Instead, the AnimatedValue should be
+        // better integrated in the cascade.
         {
             let mut builder = CustomPropertiesBuilder::new_with_properties(
                 &data.stylist,
@@ -6207,10 +6225,11 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(
             );
             let priority = CascadePriority::same_tree_author_normal_at_root_layer();
             for property in &mut iter {
-                let is_custom = match PropertyId::from_gecko_animated_property_id(&property.mProperty) {
-                    Some(PropertyId::Custom(..)) => true,
-                    _ => false,
-                };
+                let is_custom =
+                    match PropertyId::from_gecko_animated_property_id(&property.mProperty) {
+                        Some(PropertyId::Custom(..)) => true,
+                        _ => false,
+                    };
                 if !is_custom {
                     break; // Custom props are guaranteed to sort earlier.
                 }
@@ -6226,7 +6245,7 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(
                 }
             }
             iter.reset();
-            let _deferred= builder.build(DeferFontRelativeCustomPropertyResolution::No);
+            let _deferred = builder.build(DeferFontRelativeCustomPropertyResolution::No);
             debug_assert!(
                 _deferred.is_none(),
                 "Custom property processing deferred despite specifying otherwise?"
@@ -6265,7 +6284,8 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(
                         ptr::write(
                             &mut animation_values[property_index],
                             structs::PropertyStyleAnimationValuePair {
-                                mProperty: property.to_gecko_animated_property_id(/* owned = */ true),
+                                mProperty: property
+                                    .to_gecko_animated_property_id(/* owned = */ true),
                                 mValue: structs::AnimationValue {
                                     mServo: value.map_or(structs::RefPtr::null(), |v| {
                                         structs::RefPtr::from_arc(Arc::new(v))
@@ -6331,10 +6351,7 @@ pub extern "C" fn Servo_GetAnimationValues(
     let guard = global_style_data.shared_lock.read();
 
     let guard = declarations.read_with(&guard);
-    let iter = guard.to_animation_value_iter(
-        &mut context,
-        &default_values,
-    );
+    let iter = guard.to_animation_value_iter(&mut context, &default_values);
     animation_values.extend(iter.map(|v| structs::RefPtr::from_arc(Arc::new(v))));
 }
 
@@ -6385,11 +6402,7 @@ pub extern "C" fn Servo_AnimationValue_Compute(
         .next()
     {
         Some((decl, imp)) if imp == Importance::Normal => {
-            let animation = AnimationValue::from_declaration(
-                decl,
-                &mut context,
-                default_values,
-            );
+            let animation = AnimationValue::from_declaration(decl, &mut context, default_values);
             animation.map_or(Strong::null(), |value| Arc::new(value).into())
         },
         _ => Strong::null(),
@@ -7267,8 +7280,10 @@ pub extern "C" fn Servo_StyleSet_MaybeInvalidateRelativeSelectorForInsertion(
     let data = raw_data.borrow();
     let quirks_mode: QuirksMode = data.stylist.quirks_mode();
 
-    let inherited =
-        inherit_relative_selector_search_direction(element.parent_element(), element.prev_sibling_element());
+    let inherited = inherit_relative_selector_search_direction(
+        element.parent_element(),
+        element.prev_sibling_element(),
+    );
     // Technically, we're not handling breakouts, where the anchor is a (later-sibling) descendant.
     // For descendant case, we're ok since it's a descendant of an element yet to be styled.
     // For later-sibling descendant, `HAS_SLOW_SELECTOR_LATER_SIBLINGS` is set anyway.
@@ -7392,9 +7407,11 @@ fn get_siblings_of_element<'e>(
 ) -> (Option<GeckoElement<'e>>, Option<GeckoElement<'e>>) {
     let node = match following_node {
         Some(n) => n,
-        None => return match element.as_node().parent_node() {
-            Some(p) => (p.last_child_element(), None),
-            None => (None, None),
+        None => {
+            return match element.as_node().parent_node() {
+                Some(p) => (p.last_child_element(), None),
+                None => (None, None),
+            }
         },
     };
 
@@ -7416,12 +7433,12 @@ pub extern "C" fn Servo_StyleSet_MaybeInvalidateRelativeSelectorForRemoval(
         return;
     }
     let following_node = following_node.map(GeckoNode);
-    let (prev_sibling, next_sibling) =
-        get_siblings_of_element(element, &following_node);
+    let (prev_sibling, next_sibling) = get_siblings_of_element(element, &following_node);
     let data = raw_data.borrow();
     let quirks_mode: QuirksMode = data.stylist.quirks_mode();
 
-    let inherited = inherit_relative_selector_search_direction(element.parent_element(), prev_sibling);
+    let inherited =
+        inherit_relative_selector_search_direction(element.parent_element(), prev_sibling);
     if inherited.is_empty() {
         return;
     }
@@ -7951,6 +7968,74 @@ pub unsafe extern "C" fn Servo_ComputeColor(
     true
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn Servo_ColorTo(
+    from_color: &nsACString,
+    to_color_space: &nsACString,
+    result_color: &mut nsACString,
+    result_components: &mut nsTArray<f32>,
+    result_adjusted: &mut bool,
+    loader: *mut Loader,
+) -> bool {
+    // Figure out the color space.
+    let mut input = ParserInput::new(to_color_space.as_str_unchecked());
+    let mut input = Parser::new(&mut input);
+    let to_color_space = match ColorSpace::parse(&mut input) {
+        Ok(color_space) => color_space,
+        Err(_) => {
+            // Can't parse the color space? Fail the conversion.
+            return false;
+        },
+    };
+
+    let mut input = ParserInput::new(from_color.as_str_unchecked());
+    let mut input = Parser::new(&mut input);
+
+    let reporter = loader.as_mut().and_then(|loader| {
+        // Make an ErrorReporter that will report errors as being "from DOM".
+        ErrorReporter::new(ptr::null_mut(), loader, ptr::null_mut())
+    });
+
+    let context = ParserContext::new(
+        Origin::Author,
+        dummy_url_data(),
+        Some(CssRuleType::Style),
+        ParsingMode::DEFAULT,
+        QuirksMode::NoQuirks,
+        /* namespaces = */ Default::default(),
+        reporter.as_ref().map(|e| e as &dyn ParseErrorReporter),
+        None,
+    );
+
+    let specified = match specified::Color::parse(&context, &mut input) {
+        Ok(color) => color,
+        Err(_) => return false,
+    };
+
+    let color = match specified {
+        specified::Color::Absolute(ref absolute) => &absolute.color,
+        _ => {
+            // Can't do anything with a non-absolute color from here, so we
+            // fail the conversion.
+            return false;
+        },
+    };
+
+    let color = color.to_color_space(to_color_space);
+    let mut s = String::new();
+    color
+        .write_author_preferred_value(&mut CssWriter::new(&mut s))
+        .unwrap();
+    result_color.assign(&s);
+
+    result_components.assign_from_iter_pod(color.raw_components().iter().copied());
+
+    // For now we don't do gamut mapping, so always false.
+    *result_adjusted = false;
+
+    true
+}
+
 #[no_mangle]
 pub extern "C" fn Servo_ResolveColor(
     color: &computed::Color,
@@ -8919,3 +9004,58 @@ pub extern "C" fn Servo_GetSelectorWarnings(
         }
     });
 }
+
+#[no_mangle]
+pub extern "C" fn Servo_GetRuleBodyTextOffsets(
+    initial_text: &nsACString,
+    result_start_offset: &mut u32,
+    result_end_offset: &mut u32,
+) -> bool {
+    let css_text = unsafe { initial_text.as_str_unchecked() };
+    let mut input = ParserInput::new(&css_text);
+    let mut input = Parser::new(&mut input);
+
+    let mut start_offset = 0;
+    let mut found_start = false;
+
+    // Search forward for the opening brace.
+    while let Ok(token) = input.next() {
+        match *token {
+            Token::CurlyBracketBlock => {
+                start_offset = input.position().byte_index();
+                found_start = true;
+                break;
+            },
+            _ => {}
+        }
+
+        if token.is_parse_error() {
+            return false;
+        }
+    }
+
+
+    if !found_start {
+        return false;
+    }
+
+    let token_start = input.position();
+    // Parse the nested block to move the parser to the end of the block
+    let _ = input.parse_nested_block(
+        |_i| -> Result<(), CssParseError<'_, BasicParseError>> {
+            Ok(())
+        }
+    );
+    let mut end_offset = input.position().byte_index();
+    // We're not guaranteed to have a closing bracket, but when we do, we need to move
+    // the end offset before it.
+    let token_slice = input.slice_from(token_start);
+    if token_slice.ends_with("}") {
+        end_offset = end_offset - 1;
+    }
+
+    *result_start_offset = start_offset as u32;
+    *result_end_offset = end_offset as u32;
+
+    return true;
+}
diff --git a/servo/ports/geckolib/lib.rs b/servo/ports/geckolib/lib.rs
index c11f6ab36e..8f6f344d4d 100644
--- a/servo/ports/geckolib/lib.rs
+++ b/servo/ports/geckolib/lib.rs
@@ -23,6 +23,7 @@ extern crate style;
 extern crate style_traits;
 extern crate thin_vec;
 extern crate to_shmem;
+extern crate lazy_static;
 
 mod error_reporter;
 #[allow(non_snake_case)]
-- 
cgit v1.2.3