diff options
-rw-r--r-- | .travis.yml | 1 | ||||
-rw-r--r-- | components/layout/animation.rs | 6 | ||||
-rw-r--r-- | components/script/layout_wrapper.rs | 10 | ||||
-rw-r--r-- | components/script_layout_interface/restyle_damage.rs | 24 | ||||
-rw-r--r-- | components/style/animation.rs | 19 | ||||
-rw-r--r-- | components/style/dom.rs | 21 | ||||
-rw-r--r-- | components/style/gecko_glue.rs | 10 | ||||
-rw-r--r-- | components/style/matching.rs | 37 | ||||
-rw-r--r-- | components/style/restyle_hints.rs | 2 | ||||
-rw-r--r-- | components/style/sequential.rs | 2 | ||||
-rw-r--r-- | components/style/traversal.rs | 1 | ||||
-rw-r--r-- | ports/geckolib/gecko_bindings/bindings.rs | 13 | ||||
-rw-r--r-- | ports/geckolib/gecko_bindings/structs_debug.rs | 135 | ||||
-rw-r--r-- | ports/geckolib/gecko_bindings/structs_release.rs | 135 | ||||
-rwxr-xr-x | ports/geckolib/gecko_bindings/tools/regen.py | 9 | ||||
-rw-r--r-- | ports/geckolib/lib.rs | 1 | ||||
-rw-r--r-- | ports/geckolib/sanity_checks.rs | 44 | ||||
-rw-r--r-- | ports/geckolib/wrapper.rs | 65 | ||||
-rw-r--r-- | python/servo/testing_commands.py | 11 |
19 files changed, 446 insertions, 100 deletions
diff --git a/.travis.yml b/.travis.yml index 7796d98cd23..d1f71944887 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ matrix: script: - ./mach build -d --verbose - ./mach build-geckolib + - ./mach test-geckolib - ./mach test-unit - ./mach test-compiletest - bash etc/ci/check_no_unwrap.sh diff --git a/components/layout/animation.rs b/components/layout/animation.rs index 5a67b1af5bf..5222d4ba70a 100644 --- a/components/layout/animation.rs +++ b/components/layout/animation.rs @@ -14,6 +14,7 @@ use script_traits::{AnimationState, LayoutMsg as ConstellationMsg}; use std::collections::HashMap; use std::sync::mpsc::Receiver; use style::animation::{Animation, update_style_for_animation}; +use style::dom::TRestyleDamage; use style::timer::Timer; /// Processes any new animations that were discovered after style recalculation. @@ -130,10 +131,11 @@ pub fn recalc_style_for_animations(context: &SharedLayoutContext, flow.mutate_fragments(&mut |fragment| { if let Some(ref animations) = animations.get(&fragment.node) { for animation in animations.iter() { + let old_style = fragment.style.clone(); update_style_for_animation(&context.style_context, animation, - &mut fragment.style, - Some(&mut damage)); + &mut fragment.style); + damage |= RestyleDamage::compute(Some(&old_style), &fragment.style); } } }); diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs index 83245efe9f1..544eb00a560 100644 --- a/components/script/layout_wrapper.rs +++ b/components/script/layout_wrapper.rs @@ -51,6 +51,7 @@ use selectors::matching::{DeclarationBlock, ElementFlags}; use selectors::parser::{AttrSelector, NamespaceConstraint}; use std::marker::PhantomData; use std::mem::{transmute, transmute_copy}; +use std::sync::Arc; use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace}; use style::attr::AttrValue; use style::computed_values::display; @@ -58,7 +59,7 @@ use style::context::SharedStyleContext; use style::data::PrivateStyleData; use style::dom::{PresentationalHintsSynthetizer, OpaqueNode, TDocument, TElement, TNode, UnsafeNode}; use style::element_state::*; -use style::properties::{PropertyDeclaration, PropertyDeclarationBlock}; +use style::properties::{ComputedValues, PropertyDeclaration, PropertyDeclarationBlock}; use style::refcell::{Ref, RefCell, RefMut}; use style::selector_impl::{ElementSnapshot, NonTSPseudoClass, ServoSelectorImpl}; use style::sink::Push; @@ -262,6 +263,13 @@ impl<'ln> TNode for ServoLayoutNode<'ln> { self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(&node)) } } + + #[inline] + fn existing_style_for_restyle_damage<'a>(&'a self, + current_cv: Option<&'a Arc<ComputedValues>>) + -> Option<&'a Arc<ComputedValues>> { + current_cv + } } impl<'ln> LayoutNode for ServoLayoutNode<'ln> { diff --git a/components/script_layout_interface/restyle_damage.rs b/components/script_layout_interface/restyle_damage.rs index c1005099442..fc7c11d4259 100644 --- a/components/script_layout_interface/restyle_damage.rs +++ b/components/script_layout_interface/restyle_damage.rs @@ -44,21 +44,28 @@ bitflags! { } impl TRestyleDamage for RestyleDamage { - fn compute(old: Option<&Arc<ServoComputedValues>>, new: &ServoComputedValues) -> - RestyleDamage { compute_damage(old, new) } + /// For Servo the style source is always the computed values. + type PreExistingComputedValues = Arc<ServoComputedValues>; - /// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed. + fn compute(old: Option<&Arc<ServoComputedValues>>, + new: &Arc<ServoComputedValues>) -> RestyleDamage { + compute_damage(old, new) + } + + /// Returns a bitmask that represents a flow that needs to be rebuilt and + /// reflowed. /// - /// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in - /// unnecessary sequential resolution of generated content. + /// Use this instead of `RestyleDamage::all()` because + /// `RestyleDamage::all()` will result in unnecessary sequential resolution + /// of generated content. fn rebuild_and_reflow() -> RestyleDamage { REPAINT | STORE_OVERFLOW | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW } } impl RestyleDamage { - /// Supposing a flow has the given `position` property and this damage, returns the damage that - /// we should add to the *parent* of this flow. + /// Supposing a flow has the given `position` property and this damage, + /// returns the damage that we should add to the *parent* of this flow. pub fn damage_for_parent(self, child_is_absolutely_positioned: bool) -> RestyleDamage { if child_is_absolutely_positioned { self & (REPAINT | STORE_OVERFLOW | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT) @@ -143,7 +150,8 @@ macro_rules! add_if_not_equal( }) ); -fn compute_damage(old: Option<&Arc<ServoComputedValues>>, new: &ServoComputedValues) -> RestyleDamage { +fn compute_damage(old: Option<&Arc<ServoComputedValues>>, new: &Arc<ServoComputedValues>) -> RestyleDamage { + let new = &**new; let old: &ServoComputedValues = match old { None => return RestyleDamage::rebuild_and_reflow(), Some(cv) => &**cv, diff --git a/components/style/animation.rs b/components/style/animation.rs index a4600418023..1767cd49234 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -6,7 +6,7 @@ use bezier::Bezier; use context::SharedStyleContext; -use dom::{OpaqueNode, TRestyleDamage}; +use dom::OpaqueNode; use euclid::point::Point2D; use keyframes::{KeyframesStep, KeyframesStepValue}; use properties::animated_properties::{AnimatedProperty, TransitionProperty}; @@ -490,13 +490,12 @@ pub fn update_style_for_animation_frame(mut new_style: &mut Arc<ComputedValues>, } /// Updates a single animation and associated style based on the current time. /// If `damage` is provided, inserts the appropriate restyle damage. -pub fn update_style_for_animation<Damage>(context: &SharedStyleContext, - animation: &Animation, - style: &mut Arc<ComputedValues>, - damage: Option<&mut Damage>) -where Damage: TRestyleDamage { +pub fn update_style_for_animation(context: &SharedStyleContext, + animation: &Animation, + style: &mut Arc<ComputedValues>) { debug!("update_style_for_animation: entering"); debug_assert!(!animation.is_expired()); + match *animation { Animation::Transition(_, start_time, ref frame, _) => { debug!("update_style_for_animation: transition found"); @@ -506,10 +505,6 @@ where Damage: TRestyleDamage { now, start_time, frame); if updated_style { - if let Some(damage) = damage { - *damage = *damage | Damage::compute(Some(style), &new_style); - } - *style = new_style } } @@ -660,10 +655,6 @@ where Damage: TRestyleDamage { } debug!("update_style_for_animation: got style change in animation \"{}\"", name); - if let Some(damage) = damage { - *damage = *damage | Damage::compute(Some(style), &new_style); - } - *style = new_style; } } diff --git a/components/style/dom.rs b/components/style/dom.rs index c694ca75732..3406cf2815e 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -46,7 +46,19 @@ impl OpaqueNode { } pub trait TRestyleDamage : BitOr<Output=Self> + Copy { - fn compute(old: Option<&Arc<ComputedValues>>, new: &ComputedValues) -> Self; + /// The source for our current computed values in the cascade. This is a + /// ComputedValues in Servo and a StyleContext in Gecko. + /// + /// This is needed because Gecko has a few optimisations for the calculation + /// of the difference depending on which values have been used during + /// layout. + /// + /// This should be obtained via TNode::existing_style_for_restyle_damage + type PreExistingComputedValues; + + fn compute(old: Option<&Self::PreExistingComputedValues>, + new: &Arc<ComputedValues>) -> Self; + fn rebuild_and_reflow() -> Self; } @@ -159,6 +171,13 @@ pub trait TNode : Sized + Copy + Clone { fn unstyle(self) { self.mutate_data().unwrap().style = None; } + + /// XXX: It's a bit unfortunate we need to pass the current computed values + /// as an argument here, but otherwise Servo would crash due to double + /// borrows to return it. + fn existing_style_for_restyle_damage<'a>(&'a self, + current_computed_values: Option<&'a Arc<ComputedValues>>) + -> Option<&'a <Self::ConcreteRestyleDamage as TRestyleDamage>::PreExistingComputedValues>; } pub trait TDocument : Sized + Copy + Clone { diff --git a/components/style/gecko_glue.rs b/components/style/gecko_glue.rs index fadae2f57bc..d9ec0bd5562 100644 --- a/components/style/gecko_glue.rs +++ b/components/style/gecko_glue.rs @@ -13,7 +13,6 @@ pub struct ArcHelpers<GeckoType, ServoType> { phantom2: PhantomData<ServoType>, } - impl<GeckoType, ServoType> ArcHelpers<GeckoType, ServoType> { pub fn with<F, Output>(raw: *mut GeckoType, cb: F) -> Output where F: FnOnce(&Arc<ServoType>) -> Output { @@ -47,6 +46,15 @@ impl<GeckoType, ServoType> ArcHelpers<GeckoType, ServoType> { unsafe { transmute(owned) } } + pub fn borrow<F, Output>(borrowed: &Arc<ServoType>, cb: F) -> Output + where F: FnOnce(&mut GeckoType) -> Output + { + let borrowed_gecko_type: *const &mut GeckoType = + unsafe { transmute(borrowed) }; + + unsafe { cb(*borrowed_gecko_type) } + } + pub unsafe fn addref(ptr: *mut GeckoType) { Self::with(ptr, |arc| forget(arc.clone())); } diff --git a/components/style/matching.rs b/components/style/matching.rs index 2cd51352355..f8a7c0dc160 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -6,7 +6,7 @@ #![allow(unsafe_code)] -use animation::{self, Animation}; +use animation; use arc_ptr_eq; use cache::{LRUCache, SimpleHashCache}; use context::{StyleContext, SharedStyleContext}; @@ -442,8 +442,13 @@ trait PrivateMatchMethods: TNode cacheable = cacheable && !animations_started } + + let existing_style = + self.existing_style_for_restyle_damage(style.map(|s| &*s)); + // Calculate style difference. - let damage = Self::ConcreteRestyleDamage::compute(style.map(|s| &*s), &*this_style); + let damage = + Self::ConcreteRestyleDamage::compute(existing_style, &this_style); // Cache the resolved style if it was cacheable. if cacheable { @@ -490,8 +495,9 @@ trait PrivateMatchMethods: TNode // See #12171 and the associated PR for an example where this // happened while debugging other release panic. if !running_animation.is_expired() { - animation::update_style_for_animation::<Self::ConcreteRestyleDamage>( - context, running_animation, style, None); + animation::update_style_for_animation(context, + running_animation, + style); running_animation.mark_as_expired(); } } @@ -585,9 +591,17 @@ pub trait ElementMatchMethods : TElement { if let Some(shared_style) = self.share_style_with_candidate_if_possible(parent.clone(), candidate) { // Yay, cache hit. Share the style. let node = self.as_node(); + let style = &mut node.mutate_data().unwrap().style; - let damage = <<Self as TElement>::ConcreteNode as TNode> - ::ConcreteRestyleDamage::compute((*style).as_ref(), &*shared_style); + + let damage = { + let source = + node.existing_style_for_restyle_damage((*style).as_ref()); + let damage = <<Self as TElement>::ConcreteNode as TNode> + ::ConcreteRestyleDamage::compute(source, &shared_style); + damage + }; + *style = Some(shared_style); return StyleSharingResult::StyleWasShared(i, damage) } @@ -675,8 +689,14 @@ pub trait MatchMethods : TNode { let mut data_ref = self.mutate_data().unwrap(); let mut data = &mut *data_ref; let cloned_parent_style = ComputedValues::style_for_child_text_node(parent_style.unwrap()); - damage = Self::ConcreteRestyleDamage::compute(data.style.as_ref(), - &*cloned_parent_style); + + { + let existing_style = + self.existing_style_for_restyle_damage(data.style.as_ref()); + damage = Self::ConcreteRestyleDamage::compute(existing_style, + &cloned_parent_style); + } + data.style = Some(cloned_parent_style); } else { damage = { @@ -697,7 +717,6 @@ pub trait MatchMethods : TNode { let applicable_declarations_for_this_pseudo = applicable_declarations.per_pseudo.get(&pseudo).unwrap(); - if !applicable_declarations_for_this_pseudo.is_empty() { // NB: Transitions and animations should only work for // pseudo-elements ::before and ::after diff --git a/components/style/restyle_hints.rs b/components/style/restyle_hints.rs index 5dcaa147453..619aa22724b 100644 --- a/components/style/restyle_hints.rs +++ b/components/style/restyle_hints.rs @@ -28,7 +28,7 @@ bitflags! { // of a good reason for that. const RESTYLE_DESCENDANTS = 0x02, #[doc = "Rerun selector matching on all later siblings of the element and all of their descendants."] - const RESTYLE_LATER_SIBLINGS = 0x04, + const RESTYLE_LATER_SIBLINGS = 0x08, } } diff --git a/components/style/sequential.rs b/components/style/sequential.rs index 56b8a563d27..2ae7a18048b 100644 --- a/components/style/sequential.rs +++ b/components/style/sequential.rs @@ -21,7 +21,7 @@ pub fn traverse_dom<N, C>(root: N, for kid in node.children() { context.pre_process_child_hook(node, kid); - if context.should_process(node) { + if context.should_process(kid) { doit::<N, C>(context, kid); } } diff --git a/components/style/traversal.rs b/components/style/traversal.rs index d1cf9eb833b..e56db456dbf 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -12,7 +12,6 @@ use selector_impl::SelectorImplExt; use selectors::Element; use selectors::bloom::BloomFilter; use std::cell::RefCell; -use std::sync::Arc; use tid::tid; use util::opts; use values::HasViewportPercentage; diff --git a/ports/geckolib/gecko_bindings/bindings.rs b/ports/geckolib/gecko_bindings/bindings.rs index 10d2bbb7c43..646e1cffc4e 100644 --- a/ports/geckolib/gecko_bindings/bindings.rs +++ b/ports/geckolib/gecko_bindings/bindings.rs @@ -144,6 +144,10 @@ use structs::nsFont; use structs::FontFamilyList; use structs::FontFamilyType; use structs::nsIAtom; +use structs::nsStyleContext; +unsafe impl Send for nsStyleContext {} +unsafe impl Sync for nsStyleContext {} +impl HeapSizeOf for nsStyleContext { fn heap_size_of_children(&self) -> usize { 0 } } pub type RawGeckoNode = nsINode; pub enum Element { } @@ -294,10 +298,13 @@ extern "C" { pub fn Gecko_GetNodeFlags(node: *mut RawGeckoNode) -> u32; pub fn Gecko_SetNodeFlags(node: *mut RawGeckoNode, flags: u32); pub fn Gecko_UnsetNodeFlags(node: *mut RawGeckoNode, flags: u32); - pub fn Gecko_CalcAndStoreStyleDifference(element: *mut RawGeckoElement, - newstyle: - *mut ServoComputedValues) + pub fn Gecko_GetStyleContext(node: *mut RawGeckoNode) + -> *mut nsStyleContext; + pub fn Gecko_CalcStyleDifference(oldstyle: *mut nsStyleContext, + newstyle: *mut ServoComputedValues) -> nsChangeHint; + pub fn Gecko_StoreStyleDifference(node: *mut RawGeckoNode, + change: nsChangeHint); pub fn Gecko_EnsureTArrayCapacity(array: *mut ::std::os::raw::c_void, capacity: usize, elem_size: usize); pub fn Gecko_EnsureImageLayersLength(layers: *mut nsStyleImageLayers, diff --git a/ports/geckolib/gecko_bindings/structs_debug.rs b/ports/geckolib/gecko_bindings/structs_debug.rs index 1ac5b06026e..fbad408e73a 100644 --- a/ports/geckolib/gecko_bindings/structs_debug.rs +++ b/ports/geckolib/gecko_bindings/structs_debug.rs @@ -188,6 +188,12 @@ pub const NS_ERROR_MODULE_BASE_OFFSET: ::std::os::raw::c_uint = 69; pub const MOZ_STRING_WITH_OBSOLETE_API: ::std::os::raw::c_uint = 1; pub const NSID_LENGTH: ::std::os::raw::c_uint = 39; pub const NS_NUMBER_OF_FLAGS_IN_REFCNT: ::std::os::raw::c_uint = 2; +pub const _STL_PAIR_H: ::std::os::raw::c_uint = 1; +pub const _GLIBCXX_UTILITY: ::std::os::raw::c_uint = 1; +pub const __cpp_lib_tuple_element_t: ::std::os::raw::c_uint = 201402; +pub const __cpp_lib_tuples_by_type: ::std::os::raw::c_uint = 201304; +pub const __cpp_lib_exchange_function: ::std::os::raw::c_uint = 201304; +pub const __cpp_lib_integer_sequence: ::std::os::raw::c_uint = 201304; pub const NS_EVENT_STATE_HIGHEST_SERVO_BIT: ::std::os::raw::c_uint = 6; pub const DOM_USER_DATA: ::std::os::raw::c_uint = 1; pub const SMIL_MAPPED_ATTR_ANIMVAL: ::std::os::raw::c_uint = 2; @@ -1484,6 +1490,53 @@ pub enum nsresult { NS_OK_NO_NAME_CLAUSE_HANDLED = 7864354, } pub type nsrefcnt = MozRefCountType; +#[repr(C)] +#[derive(Debug, Copy)] +pub struct HasPointerTypeHelper; +impl ::std::clone::Clone for HasPointerTypeHelper { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct PointerType<T, D> { + pub _phantom0: ::std::marker::PhantomData<T>, + pub _phantom1: ::std::marker::PhantomData<D>, +} +/** + * <div rustbindgen="true" replaces="UniquePtr"> + * + * TODO(Emilio): This is a workaround and we should be able to get rid of this + * one. + */ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UniquePtr<T, Deleter> { + pub mPtr: *mut T, + pub _phantom0: ::std::marker::PhantomData<Deleter>, +} +/** + * A default deletion policy using plain old operator delete. + * + * Note that this type can be specialized, but authors should beware of the risk + * that the specialization may at some point cease to match (either because it + * gets moved to a different compilation unit or the signature changes). If the + * non-specialized (|delete|-based) version compiles for that type but does the + * wrong thing, bad things could happen. + * + * This is a non-issue for types which are always incomplete (i.e. opaque handle + * types), since |delete|-ing such a type will always trigger a compilation + * error. + */ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DefaultDelete<T> { + pub _phantom0: ::std::marker::PhantomData<T>, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UniqueSelector<T> { + pub _phantom0: ::std::marker::PhantomData<T>, +} /** * typedefs for backwards compatibility */ @@ -2703,6 +2756,12 @@ impl ::std::clone::Clone for nsIExpandedPrincipal { fn clone(&self) -> Self { *self } } #[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _Make_integer_sequence<_Tp, _ISeq> { + pub _phantom0: ::std::marker::PhantomData<_Tp>, + pub _phantom1: ::std::marker::PhantomData<_ISeq>, +} +#[repr(C)] #[derive(Debug, Copy)] pub struct nsIURI { pub _base: nsISupports, @@ -2754,7 +2813,7 @@ impl ::std::clone::Clone for nsIRequest { #[repr(C)] #[derive(Debug, Copy)] pub struct EventStates { - pub mStates: ::std::os::raw::c_ulonglong, + pub mStates: ::std::os::raw::c_ulong, } impl ::std::clone::Clone for EventStates { fn clone(&self) -> Self { *self } @@ -2818,11 +2877,6 @@ pub enum nsNodeSupportsWeakRefTearoff { } pub enum nsNodeWeakReference { } pub enum nsDOMMutationObserver { } pub enum ServoNodeData { } -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct DefaultDelete<> { - pub _phantom0: ::std::marker::PhantomData<ServoNodeData>, -} pub enum EventListenerManager { } pub enum BoxQuadOptions { } pub enum ConvertCoordinateOptions { } @@ -2889,7 +2943,7 @@ fn bindgen_test_layout_nsMutationGuard() { extern "C" { #[link_name = "_ZN15nsMutationGuard11sGenerationE"] pub static mut nsMutationGuard_consts_sGeneration: - ::std::os::raw::c_ulonglong; + ::std::os::raw::c_ulong; } pub type Float = f32; #[repr(i8)] @@ -3280,7 +3334,7 @@ pub type nscolor = u32; #[repr(i8)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum nsHexColorType { NoAlpha = 0, AllowAlpha = 1, } -pub enum nsStyledElementNotElementCSSInlineStyle { } +pub enum nsStyledElement { } pub enum MiscContainer { } pub enum ServoDeclarationBlock { } pub enum Declaration { } @@ -3491,12 +3545,7 @@ fn bindgen_test_layout_ServoAttrSnapshot() { */ #[repr(i8)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum ServoElementSnapshotFlags { - State = 1, - Attributes = 2, - HTMLElementInHTMLDocument = 4, - All = 7, -} +pub enum ServoElementSnapshotFlags { State = 1, Attributes = 2, All = 3, } /** * This class holds all non-tree-structural state of an element that might be * used for selector matching eventually. @@ -3513,6 +3562,7 @@ pub struct ServoElementSnapshot { pub mExplicitRestyleHint: nsRestyleHint, pub mExplicitChangeHint: nsChangeHint, pub mIsHTMLElementInHTMLDocument: bool, + pub mIsInChromeDocument: bool, } #[test] fn bindgen_test_layout_ServoElementSnapshot() { @@ -5362,6 +5412,16 @@ pub enum nsStyleImageType { eStyleImageType_Gradient = 2, eStyleImageType_Element = 3, } +#[repr(C)] +pub struct CachedBorderImageData { + pub mCachedSVGViewportSize: [u64; 2usize], + pub mSubImages: u64, +} +#[test] +fn bindgen_test_layout_CachedBorderImageData() { + assert_eq!(::std::mem::size_of::<CachedBorderImageData>() , 24usize); + assert_eq!(::std::mem::align_of::<CachedBorderImageData>() , 8usize); +} /** * Represents a paintable image of one of the following types. * (1) A real image loaded from an external source. @@ -5374,10 +5434,11 @@ pub enum nsStyleImageType { */ #[repr(C)] pub struct nsStyleImage { - pub mSubImages: u64, + pub mCachedBIData: UniquePtr<CachedBorderImageData, + DefaultDelete<CachedBorderImageData>>, pub mType: nsStyleImageType, pub nsStyleImage_nsStyleStruct_h_unnamed_21: nsStyleImage_nsStyleStruct_h_unnamed_21, - pub mCropRect: nsAutoPtr<nsStyleSides>, + pub mCropRect: UniquePtr<nsStyleSides, DefaultDelete<nsStyleSides>>, pub mImageTracked: bool, } #[repr(C)] @@ -6261,6 +6322,17 @@ extern "C" { #[link_name = "_ZN13nsStyleColumn15kMaxColumnCountE"] pub static nsStyleColumn_consts_kMaxColumnCount: ::std::os::raw::c_uint; } +#[repr(C)] +#[derive(Debug)] +pub struct FragmentOrURL { + pub mURL: nsCOMPtr<nsIURI>, + pub mIsLocalRef: bool, +} +#[test] +fn bindgen_test_layout_FragmentOrURL() { + assert_eq!(::std::mem::size_of::<FragmentOrURL>() , 16usize); + assert_eq!(::std::mem::align_of::<FragmentOrURL>() , 8usize); +} #[repr(u32)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum nsStyleSVGPaintType { @@ -6288,7 +6360,7 @@ pub struct nsStyleSVGPaint { #[derive(Debug, Copy)] pub struct nsStyleSVGPaint_nsStyleStruct_h_unnamed_27 { pub mColor: __BindgenUnionField<nscolor>, - pub mPaintServer: __BindgenUnionField<*mut nsIURI>, + pub mPaintServer: __BindgenUnionField<*mut FragmentOrURL>, pub _bindgen_data_: u64, } impl nsStyleSVGPaint_nsStyleStruct_h_unnamed_27 { } @@ -6312,9 +6384,9 @@ fn bindgen_test_layout_nsStyleSVGPaint() { pub struct nsStyleSVG { pub mFill: nsStyleSVGPaint, pub mStroke: nsStyleSVGPaint, - pub mMarkerEnd: nsCOMPtr<nsIURI>, - pub mMarkerMid: nsCOMPtr<nsIURI>, - pub mMarkerStart: nsCOMPtr<nsIURI>, + pub mMarkerEnd: FragmentOrURL, + pub mMarkerMid: FragmentOrURL, + pub mMarkerStart: FragmentOrURL, pub mStrokeDasharray: nsTArray<nsStyleCoord>, pub mStrokeDashoffset: nsStyleCoord, pub mStrokeWidth: nsStyleCoord, @@ -6345,7 +6417,7 @@ pub enum nsStyleSVG_nsStyleStruct_h_unnamed_28 { } #[test] fn bindgen_test_layout_nsStyleSVG() { - assert_eq!(::std::mem::size_of::<nsStyleSVG>() , 120usize); + assert_eq!(::std::mem::size_of::<nsStyleSVG>() , 144usize); assert_eq!(::std::mem::align_of::<nsStyleSVG>() , 8usize); } #[repr(C)] @@ -6383,7 +6455,7 @@ pub struct nsStyleClipPath { #[derive(Debug, Copy)] pub struct nsStyleClipPath_nsStyleStruct_h_unnamed_29 { pub mBasicShape: __BindgenUnionField<*mut nsStyleBasicShape>, - pub mURL: __BindgenUnionField<*mut nsIURI>, + pub mURL: __BindgenUnionField<*mut FragmentOrURL>, pub _bindgen_data_: u64, } impl nsStyleClipPath_nsStyleStruct_h_unnamed_29 { } @@ -6412,7 +6484,7 @@ pub struct nsStyleFilter { #[repr(C)] #[derive(Debug, Copy)] pub struct nsStyleFilter_nsStyleStruct_h_unnamed_30 { - pub mURL: __BindgenUnionField<*mut nsIURI>, + pub mURL: __BindgenUnionField<*mut FragmentOrURL>, pub mDropShadow: __BindgenUnionField<*mut nsCSSShadowArray>, pub _bindgen_data_: u64, } @@ -6474,3 +6546,20 @@ fn bindgen_test_layout_nsStyleEffects() { assert_eq!(::std::mem::size_of::<nsStyleEffects>() , 40usize); assert_eq!(::std::mem::align_of::<nsStyleEffects>() , 8usize); } +/** + * <div rustbindgen="true" replaces="nsSize"> + */ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct nsSize { + pub width: nscoord, + pub height: nscoord, +} +impl ::std::clone::Clone for nsSize { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_nsSize() { + assert_eq!(::std::mem::size_of::<nsSize>() , 8usize); + assert_eq!(::std::mem::align_of::<nsSize>() , 4usize); +} diff --git a/ports/geckolib/gecko_bindings/structs_release.rs b/ports/geckolib/gecko_bindings/structs_release.rs index 418b428cc16..111bb6347a2 100644 --- a/ports/geckolib/gecko_bindings/structs_release.rs +++ b/ports/geckolib/gecko_bindings/structs_release.rs @@ -188,6 +188,12 @@ pub const NS_ERROR_MODULE_BASE_OFFSET: ::std::os::raw::c_uint = 69; pub const MOZ_STRING_WITH_OBSOLETE_API: ::std::os::raw::c_uint = 1; pub const NSID_LENGTH: ::std::os::raw::c_uint = 39; pub const NS_NUMBER_OF_FLAGS_IN_REFCNT: ::std::os::raw::c_uint = 2; +pub const _STL_PAIR_H: ::std::os::raw::c_uint = 1; +pub const _GLIBCXX_UTILITY: ::std::os::raw::c_uint = 1; +pub const __cpp_lib_tuple_element_t: ::std::os::raw::c_uint = 201402; +pub const __cpp_lib_tuples_by_type: ::std::os::raw::c_uint = 201304; +pub const __cpp_lib_exchange_function: ::std::os::raw::c_uint = 201304; +pub const __cpp_lib_integer_sequence: ::std::os::raw::c_uint = 201304; pub const NS_EVENT_STATE_HIGHEST_SERVO_BIT: ::std::os::raw::c_uint = 6; pub const DOM_USER_DATA: ::std::os::raw::c_uint = 1; pub const SMIL_MAPPED_ATTR_ANIMVAL: ::std::os::raw::c_uint = 2; @@ -1484,6 +1490,53 @@ pub enum nsresult { NS_OK_NO_NAME_CLAUSE_HANDLED = 7864354, } pub type nsrefcnt = MozRefCountType; +#[repr(C)] +#[derive(Debug, Copy)] +pub struct HasPointerTypeHelper; +impl ::std::clone::Clone for HasPointerTypeHelper { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct PointerType<T, D> { + pub _phantom0: ::std::marker::PhantomData<T>, + pub _phantom1: ::std::marker::PhantomData<D>, +} +/** + * <div rustbindgen="true" replaces="UniquePtr"> + * + * TODO(Emilio): This is a workaround and we should be able to get rid of this + * one. + */ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UniquePtr<T, Deleter> { + pub mPtr: *mut T, + pub _phantom0: ::std::marker::PhantomData<Deleter>, +} +/** + * A default deletion policy using plain old operator delete. + * + * Note that this type can be specialized, but authors should beware of the risk + * that the specialization may at some point cease to match (either because it + * gets moved to a different compilation unit or the signature changes). If the + * non-specialized (|delete|-based) version compiles for that type but does the + * wrong thing, bad things could happen. + * + * This is a non-issue for types which are always incomplete (i.e. opaque handle + * types), since |delete|-ing such a type will always trigger a compilation + * error. + */ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct DefaultDelete<T> { + pub _phantom0: ::std::marker::PhantomData<T>, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct UniqueSelector<T> { + pub _phantom0: ::std::marker::PhantomData<T>, +} /** * typedefs for backwards compatibility */ @@ -2682,6 +2735,12 @@ impl ::std::clone::Clone for nsIExpandedPrincipal { fn clone(&self) -> Self { *self } } #[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _Make_integer_sequence<_Tp, _ISeq> { + pub _phantom0: ::std::marker::PhantomData<_Tp>, + pub _phantom1: ::std::marker::PhantomData<_ISeq>, +} +#[repr(C)] #[derive(Debug, Copy)] pub struct nsIURI { pub _base: nsISupports, @@ -2733,7 +2792,7 @@ impl ::std::clone::Clone for nsIRequest { #[repr(C)] #[derive(Debug, Copy)] pub struct EventStates { - pub mStates: ::std::os::raw::c_ulonglong, + pub mStates: ::std::os::raw::c_ulong, } impl ::std::clone::Clone for EventStates { fn clone(&self) -> Self { *self } @@ -2797,11 +2856,6 @@ pub enum nsNodeSupportsWeakRefTearoff { } pub enum nsNodeWeakReference { } pub enum nsDOMMutationObserver { } pub enum ServoNodeData { } -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct DefaultDelete<> { - pub _phantom0: ::std::marker::PhantomData<ServoNodeData>, -} pub enum EventListenerManager { } pub enum BoxQuadOptions { } pub enum ConvertCoordinateOptions { } @@ -2868,7 +2922,7 @@ fn bindgen_test_layout_nsMutationGuard() { extern "C" { #[link_name = "_ZN15nsMutationGuard11sGenerationE"] pub static mut nsMutationGuard_consts_sGeneration: - ::std::os::raw::c_ulonglong; + ::std::os::raw::c_ulong; } pub type Float = f32; #[repr(i8)] @@ -3259,7 +3313,7 @@ pub type nscolor = u32; #[repr(i8)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum nsHexColorType { NoAlpha = 0, AllowAlpha = 1, } -pub enum nsStyledElementNotElementCSSInlineStyle { } +pub enum nsStyledElement { } pub enum MiscContainer { } pub enum ServoDeclarationBlock { } pub enum Declaration { } @@ -3470,12 +3524,7 @@ fn bindgen_test_layout_ServoAttrSnapshot() { */ #[repr(i8)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub enum ServoElementSnapshotFlags { - State = 1, - Attributes = 2, - HTMLElementInHTMLDocument = 4, - All = 7, -} +pub enum ServoElementSnapshotFlags { State = 1, Attributes = 2, All = 3, } /** * This class holds all non-tree-structural state of an element that might be * used for selector matching eventually. @@ -3492,6 +3541,7 @@ pub struct ServoElementSnapshot { pub mExplicitRestyleHint: nsRestyleHint, pub mExplicitChangeHint: nsChangeHint, pub mIsHTMLElementInHTMLDocument: bool, + pub mIsInChromeDocument: bool, } #[test] fn bindgen_test_layout_ServoElementSnapshot() { @@ -5341,6 +5391,16 @@ pub enum nsStyleImageType { eStyleImageType_Gradient = 2, eStyleImageType_Element = 3, } +#[repr(C)] +pub struct CachedBorderImageData { + pub mCachedSVGViewportSize: [u64; 2usize], + pub mSubImages: u64, +} +#[test] +fn bindgen_test_layout_CachedBorderImageData() { + assert_eq!(::std::mem::size_of::<CachedBorderImageData>() , 24usize); + assert_eq!(::std::mem::align_of::<CachedBorderImageData>() , 8usize); +} /** * Represents a paintable image of one of the following types. * (1) A real image loaded from an external source. @@ -5353,10 +5413,11 @@ pub enum nsStyleImageType { */ #[repr(C)] pub struct nsStyleImage { - pub mSubImages: u64, + pub mCachedBIData: UniquePtr<CachedBorderImageData, + DefaultDelete<CachedBorderImageData>>, pub mType: nsStyleImageType, pub nsStyleImage_nsStyleStruct_h_unnamed_21: nsStyleImage_nsStyleStruct_h_unnamed_21, - pub mCropRect: nsAutoPtr<nsStyleSides>, + pub mCropRect: UniquePtr<nsStyleSides, DefaultDelete<nsStyleSides>>, } #[repr(C)] #[derive(Debug, Copy)] @@ -6238,6 +6299,17 @@ extern "C" { #[link_name = "_ZN13nsStyleColumn15kMaxColumnCountE"] pub static nsStyleColumn_consts_kMaxColumnCount: ::std::os::raw::c_uint; } +#[repr(C)] +#[derive(Debug)] +pub struct FragmentOrURL { + pub mURL: nsCOMPtr<nsIURI>, + pub mIsLocalRef: bool, +} +#[test] +fn bindgen_test_layout_FragmentOrURL() { + assert_eq!(::std::mem::size_of::<FragmentOrURL>() , 16usize); + assert_eq!(::std::mem::align_of::<FragmentOrURL>() , 8usize); +} #[repr(u32)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum nsStyleSVGPaintType { @@ -6265,7 +6337,7 @@ pub struct nsStyleSVGPaint { #[derive(Debug, Copy)] pub struct nsStyleSVGPaint_nsStyleStruct_h_unnamed_27 { pub mColor: __BindgenUnionField<nscolor>, - pub mPaintServer: __BindgenUnionField<*mut nsIURI>, + pub mPaintServer: __BindgenUnionField<*mut FragmentOrURL>, pub _bindgen_data_: u64, } impl nsStyleSVGPaint_nsStyleStruct_h_unnamed_27 { } @@ -6289,9 +6361,9 @@ fn bindgen_test_layout_nsStyleSVGPaint() { pub struct nsStyleSVG { pub mFill: nsStyleSVGPaint, pub mStroke: nsStyleSVGPaint, - pub mMarkerEnd: nsCOMPtr<nsIURI>, - pub mMarkerMid: nsCOMPtr<nsIURI>, - pub mMarkerStart: nsCOMPtr<nsIURI>, + pub mMarkerEnd: FragmentOrURL, + pub mMarkerMid: FragmentOrURL, + pub mMarkerStart: FragmentOrURL, pub mStrokeDasharray: nsTArray<nsStyleCoord>, pub mStrokeDashoffset: nsStyleCoord, pub mStrokeWidth: nsStyleCoord, @@ -6322,7 +6394,7 @@ pub enum nsStyleSVG_nsStyleStruct_h_unnamed_28 { } #[test] fn bindgen_test_layout_nsStyleSVG() { - assert_eq!(::std::mem::size_of::<nsStyleSVG>() , 120usize); + assert_eq!(::std::mem::size_of::<nsStyleSVG>() , 144usize); assert_eq!(::std::mem::align_of::<nsStyleSVG>() , 8usize); } #[repr(C)] @@ -6360,7 +6432,7 @@ pub struct nsStyleClipPath { #[derive(Debug, Copy)] pub struct nsStyleClipPath_nsStyleStruct_h_unnamed_29 { pub mBasicShape: __BindgenUnionField<*mut nsStyleBasicShape>, - pub mURL: __BindgenUnionField<*mut nsIURI>, + pub mURL: __BindgenUnionField<*mut FragmentOrURL>, pub _bindgen_data_: u64, } impl nsStyleClipPath_nsStyleStruct_h_unnamed_29 { } @@ -6389,7 +6461,7 @@ pub struct nsStyleFilter { #[repr(C)] #[derive(Debug, Copy)] pub struct nsStyleFilter_nsStyleStruct_h_unnamed_30 { - pub mURL: __BindgenUnionField<*mut nsIURI>, + pub mURL: __BindgenUnionField<*mut FragmentOrURL>, pub mDropShadow: __BindgenUnionField<*mut nsCSSShadowArray>, pub _bindgen_data_: u64, } @@ -6451,3 +6523,20 @@ fn bindgen_test_layout_nsStyleEffects() { assert_eq!(::std::mem::size_of::<nsStyleEffects>() , 40usize); assert_eq!(::std::mem::align_of::<nsStyleEffects>() , 8usize); } +/** + * <div rustbindgen="true" replaces="nsSize"> + */ +#[repr(C)] +#[derive(Debug, Copy)] +pub struct nsSize { + pub width: nscoord, + pub height: nscoord, +} +impl ::std::clone::Clone for nsSize { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_nsSize() { + assert_eq!(::std::mem::size_of::<nsSize>() , 8usize); + assert_eq!(::std::mem::align_of::<nsSize>() , 4usize); +} diff --git a/ports/geckolib/gecko_bindings/tools/regen.py b/ports/geckolib/gecko_bindings/tools/regen.py index 821a5e475a7..653213f848d 100755 --- a/ports/geckolib/gecko_bindings/tools/regen.py +++ b/ports/geckolib/gecko_bindings/tools/regen.py @@ -80,6 +80,7 @@ COMPILATION_TARGETS = { "/Types.h", # <- Disallow UnionTypes.h "/utility", # <- Disallow xutility "nsINode.h", # <- For `NodeFlags`. + "UniquePtr.h" ], "blacklist": [ "IsDestructibleFallbackImpl", "IsDestructibleFallback", @@ -90,13 +91,17 @@ COMPILATION_TARGETS = { "FastAnimationEffectTimingProperties", "ComputedTimingProperties", "FastComputedTimingProperties", "nsINode", + "HasPointerType" ], "opaque_types": [ "nsIntMargin", "nsIntPoint", "nsIntRect", "nsCOMArray", "nsDependentString", "EntryStore", "gfxFontFeatureValueSet", "imgRequestProxy", "imgRequestProxyStatic", "CounterStyleManager", "ImageValue", "URLValue", "URLValueData", "nsIPrincipal", - "nsDataHashtable", "imgIRequest" + "nsDataHashtable", "imgIRequest", + "Maybe", # <- AlignedStorage, which means templated union, which + # means impossible to represent in stable rust as of + # right now. ], }, # Generation of the ffi bindings. @@ -128,7 +133,7 @@ COMPILATION_TARGETS = { "nsStyleCoord::Calc", "nsRestyleHint", "ServoElementSnapshot", "nsChangeHint", "SheetParsingMode", "nsMainThreadPtrHandle", "nsMainThreadPtrHolder", "nscolor", "nsFont", "FontFamilyList", - "FontFamilyType", "nsIAtom", + "FontFamilyType", "nsIAtom", "nsStyleContext" ], "void_types": [ "nsINode", "nsIDocument", "nsIPrincipal", "nsIURI", diff --git a/ports/geckolib/lib.rs b/ports/geckolib/lib.rs index 81923a9188c..c5c31eae733 100644 --- a/ports/geckolib/lib.rs +++ b/ports/geckolib/lib.rs @@ -26,6 +26,7 @@ mod snapshot; mod snapshot_helpers; #[allow(non_snake_case)] pub mod glue; +mod sanity_checks; mod traversal; mod wrapper; diff --git a/ports/geckolib/sanity_checks.rs b/ports/geckolib/sanity_checks.rs new file mode 100644 index 00000000000..96fd1e555b3 --- /dev/null +++ b/ports/geckolib/sanity_checks.rs @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Different static asserts that ensure the build does what it's expected to. +//! +//! TODO: maybe cfg(test) this? + +#![allow(unused_imports)] + +use std::mem; + +macro_rules! check_enum_value { + ($a:expr, $b:expr) => { + unsafe { + mem::transmute::<[u32; $a as usize], + [u32; $b as usize]>([0; $a as usize]); + } + } +} + +// NB: It's a shame we can't do this statically with bitflags, but no +// const-fn and no other way to access the numerical value :-( +macro_rules! check_enum_value_non_static { + ($a:expr, $b:expr) => { + assert_eq!($a as usize, $b as usize); + } +} + +#[test] +fn assert_restyle_hints_match() { + use style::restyle_hints::*; // For flags + use gecko_bindings::structs::nsRestyleHint; + + check_enum_value_non_static!(nsRestyleHint::eRestyle_Self, RESTYLE_SELF.bits()); + // XXX This for Servo actually means something like an hypothetical + // Restyle_AllDescendants (but without running selector matching on the + // element). ServoRestyleManager interprets it like that, but in practice we + // should align the behavior with Gecko adding a new restyle hint, maybe? + // + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1291786 + check_enum_value_non_static!(nsRestyleHint::eRestyle_SomeDescendants, RESTYLE_DESCENDANTS.bits()); + check_enum_value_non_static!(nsRestyleHint::eRestyle_LaterSiblings, RESTYLE_LATER_SIBLINGS.bits()); +} diff --git a/ports/geckolib/wrapper.rs b/ports/geckolib/wrapper.rs index d71666975a0..b750fda883f 100644 --- a/ports/geckolib/wrapper.rs +++ b/ports/geckolib/wrapper.rs @@ -8,7 +8,10 @@ use gecko_bindings::bindings; use gecko_bindings::bindings::Gecko_ChildrenCount; use gecko_bindings::bindings::Gecko_ClassOrClassList; use gecko_bindings::bindings::Gecko_GetNodeData; +use gecko_bindings::bindings::Gecko_GetStyleContext; +use gecko_bindings::bindings::ServoComputedValues; use gecko_bindings::bindings::ServoNodeData; +use gecko_bindings::bindings::{Gecko_CalcStyleDifference, Gecko_StoreStyleDifference}; use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentElement}; use gecko_bindings::bindings::{Gecko_GetFirstChild, Gecko_GetFirstChildElement}; use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetLastChildElement}; @@ -21,8 +24,8 @@ use gecko_bindings::bindings::{Gecko_IsLink, Gecko_IsRootElement, Gecko_IsTextNo use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink}; use gecko_bindings::bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData}; use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode}; -use gecko_bindings::structs::nsIAtom; use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO}; +use gecko_bindings::structs::{nsIAtom, nsChangeHint, nsStyleContext}; use glue::GeckoDeclarationBlock; use libc::uintptr_t; use selectors::Element; @@ -40,6 +43,7 @@ use style::dom::{OpaqueNode, PresentationalHintsSynthetizer}; use style::dom::{TDocument, TElement, TNode, TRestyleDamage, UnsafeNode}; use style::element_state::ElementState; use style::error_reporting::StdoutErrorReporter; +use style::gecko_glue::ArcHelpers; use style::gecko_selector_impl::{GeckoSelectorImpl, NonTSPseudoClass}; use style::parser::ParserContextExtraData; use style::properties::{ComputedValues, parse_style_attribute}; @@ -91,14 +95,36 @@ impl<'ln> GeckoNode<'ln> { } #[derive(Clone, Copy)] -pub struct DummyRestyleDamage; -impl TRestyleDamage for DummyRestyleDamage { - fn compute(_: Option<&Arc<ComputedValues>>, _: &ComputedValues) -> Self { DummyRestyleDamage } - fn rebuild_and_reflow() -> Self { DummyRestyleDamage } +pub struct GeckoRestyleDamage(nsChangeHint); + +impl TRestyleDamage for GeckoRestyleDamage { + type PreExistingComputedValues = nsStyleContext; + fn compute(source: Option<&nsStyleContext>, + new_style: &Arc<ComputedValues>) -> Self { + type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>; + let context = match source { + Some(ctx) => ctx as *const nsStyleContext as *mut nsStyleContext, + None => return Self::rebuild_and_reflow(), + }; + + Helpers::borrow(new_style, |new_style| { + let hint = unsafe { Gecko_CalcStyleDifference(context, new_style) }; + GeckoRestyleDamage(hint) + }) + } + + fn rebuild_and_reflow() -> Self { + GeckoRestyleDamage(nsChangeHint::nsChangeHint_ReconstructFrame) + } } -impl BitOr for DummyRestyleDamage { + +impl BitOr for GeckoRestyleDamage { type Output = Self; - fn bitor(self, _: Self) -> Self { DummyRestyleDamage } + + fn bitor(self, other: Self) -> Self { + use std::mem; + GeckoRestyleDamage(unsafe { mem::transmute(self.0 as u32 | other.0 as u32) }) + } } @@ -106,7 +132,7 @@ impl BitOr for DummyRestyleDamage { impl<'ln> TNode for GeckoNode<'ln> { type ConcreteDocument = GeckoDocument<'ln>; type ConcreteElement = GeckoElement<'ln>; - type ConcreteRestyleDamage = DummyRestyleDamage; + type ConcreteRestyleDamage = GeckoRestyleDamage; fn to_unsafe(&self) -> UnsafeNode { (self.node as usize, 0) @@ -243,9 +269,14 @@ impl<'ln> TNode for GeckoNode<'ln> { } } - fn restyle_damage(self) -> Self::ConcreteRestyleDamage { DummyRestyleDamage } + fn restyle_damage(self) -> Self::ConcreteRestyleDamage { + // Not called from style, only for layout. + unimplemented!(); + } - fn set_restyle_damage(self, _: Self::ConcreteRestyleDamage) {} + fn set_restyle_damage(self, damage: Self::ConcreteRestyleDamage) { + unsafe { Gecko_StoreStyleDifference(self.node, damage.0) } + } fn parent_node(&self) -> Option<GeckoNode<'ln>> { unsafe { @@ -277,6 +308,20 @@ impl<'ln> TNode for GeckoNode<'ln> { } } + fn existing_style_for_restyle_damage<'a>(&'a self, + current_cv: Option<&'a Arc<ComputedValues>>) + -> Option<&'a nsStyleContext> { + if current_cv.is_none() { + // Don't bother in doing an ffi call to get null back. + return None; + } + + unsafe { + let context_ptr = Gecko_GetStyleContext(self.node); + context_ptr.as_ref() + } + } + fn needs_dirty_on_viewport_size_changed(&self) -> bool { // Gecko's node doesn't have the DIRTY_ON_VIEWPORT_SIZE_CHANGE flag, // so we force them to be dirtied on viewport size change, regardless if diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py index 4776a9209d1..5eaad0ba7b9 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -158,6 +158,17 @@ class MachCommands(CommandBase): return suite return None + @Command('test-geckolib', + description='Test geckolib sanity checks', + category='testing') + def test_geckolib(self): + self.ensure_bootstrapped() + + env = self.build_env() + env["RUST_BACKTRACE"] = "1" + + return call(["cargo", "test"], env=env, cwd=path.join("ports", "geckolib")) + @Command('test-unit', description='Run unit tests', category='testing') |