aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--components/layout/animation.rs6
-rw-r--r--components/script/layout_wrapper.rs10
-rw-r--r--components/script_layout_interface/restyle_damage.rs24
-rw-r--r--components/style/animation.rs19
-rw-r--r--components/style/dom.rs21
-rw-r--r--components/style/gecko_glue.rs10
-rw-r--r--components/style/matching.rs37
-rw-r--r--components/style/restyle_hints.rs2
-rw-r--r--components/style/sequential.rs2
-rw-r--r--components/style/traversal.rs1
-rw-r--r--ports/geckolib/gecko_bindings/bindings.rs13
-rw-r--r--ports/geckolib/gecko_bindings/structs_debug.rs135
-rw-r--r--ports/geckolib/gecko_bindings/structs_release.rs135
-rwxr-xr-xports/geckolib/gecko_bindings/tools/regen.py9
-rw-r--r--ports/geckolib/lib.rs1
-rw-r--r--ports/geckolib/sanity_checks.rs44
-rw-r--r--ports/geckolib/wrapper.rs65
-rw-r--r--python/servo/testing_commands.py11
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')