Auto merge of #16145 - hiikezoe:animation-only-restyles, r=heycam

Animation only restyles

<!-- Please describe your changes on the following line: -->
This is a PR of https://bugzilla.mozilla.org/show_bug.cgi?id=1344966

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors

<!-- Either: -->
- [X] These changes do not require tests because it's for stylo.

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16145)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-03-26 21:13:44 -07:00 committed by GitHub
commit d77fceaf24
11 changed files with 1081 additions and 1079 deletions

View file

@ -120,7 +120,7 @@ use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets};
use style::stylist::Stylist;
use style::thread_state;
use style::timer::Timer;
use style::traversal::{DomTraversal, TraversalDriver};
use style::traversal::{DomTraversal, TraversalDriver, TraversalFlags};
/// Information needed by the layout thread.
pub struct LayoutThread {
@ -520,6 +520,7 @@ impl LayoutThread {
local_context_creation_data: Mutex::new(thread_local_style_context_creation_data),
timer: self.timer.clone(),
quirks_mode: self.quirks_mode.unwrap(),
animation_only_restyle: false,
},
image_cache_thread: Mutex::new(self.image_cache_thread.clone()),
font_cache_thread: Mutex::new(self.font_cache_thread.clone()),
@ -1143,7 +1144,7 @@ impl LayoutThread {
let stylist = &<RecalcStyleAndConstructFlows as
DomTraversal<ServoLayoutElement>>::shared_context(&traversal).stylist;
<RecalcStyleAndConstructFlows as
DomTraversal<ServoLayoutElement>>::pre_traverse(element, stylist, /* skip_root = */ false)
DomTraversal<ServoLayoutElement>>::pre_traverse(element, stylist, TraversalFlags::empty())
};
if token.should_traverse() {

View file

@ -87,6 +87,9 @@ pub struct SharedStyleContext<'a> {
/// The QuirksMode state which the document needs to be rendered with
pub quirks_mode: QuirksMode,
/// True if the traversal is processing only animation restyles.
pub animation_only_restyle: bool,
}
impl<'a> SharedStyleContext<'a> {

View file

@ -9,7 +9,7 @@
use dom::TElement;
use properties::ComputedValues;
use properties::longhands::display::computed_value as display;
use restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
use restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
use rule_tree::StrongRuleNode;
use selector_parser::{PseudoElement, RestyleDamage, Snapshot};
use std::collections::HashMap;
@ -136,7 +136,12 @@ pub struct StoredRestyleHint(RestyleHint);
impl StoredRestyleHint {
/// Propagates this restyle hint to a child element.
pub fn propagate(&self) -> Self {
StoredRestyleHint(if self.0.contains(RESTYLE_DESCENDANTS) {
// If we have RESTYLE_CSS_ANIMATIONS restyle hint, it means we are in the
// middle of an animation only restyle. In that case, we don't need to
// propagate any restyle hints.
StoredRestyleHint(if self.0.contains(RESTYLE_CSS_ANIMATIONS) {
RestyleHint::empty()
} else if self.0.contains(RESTYLE_DESCENDANTS) {
RESTYLE_SELF | RESTYLE_DESCENDANTS
} else {
RestyleHint::empty()
@ -174,6 +179,16 @@ impl StoredRestyleHint {
pub fn insert(&mut self, other: &Self) {
self.0 |= other.0
}
/// Remove animation restyle hint.
pub fn remove_animation_hint(&mut self) {
self.0.remove(RESTYLE_CSS_ANIMATIONS)
}
/// Returns true if the hint has animation-only restyle.
pub fn has_animation_hint(&self) -> bool {
self.0.contains(RESTYLE_CSS_ANIMATIONS)
}
}
impl Default for StoredRestyleHint {

View file

@ -309,6 +309,24 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
/// Only safe to call with exclusive access to the element.
unsafe fn unset_dirty_descendants(&self);
/// Similar to the dirty_descendants but for representing a descendant of
/// the element needs to be updated in animation-only traversal.
fn has_animation_only_dirty_descendants(&self) -> bool {
false
}
/// Flag that this element has a descendant for animation-only restyle processing.
///
/// Only safe to call with exclusive access to the element.
unsafe fn set_animation_only_dirty_descendants(&self) {
}
/// Flag that this element has no descendant for animation-only restyle processing.
///
/// Only safe to call with exclusive access to the element.
unsafe fn unset_animation_only_dirty_descendants(&self) {
}
/// Atomically stores the number of children of this node that we will
/// need to process during bottom-up traversal.
fn store_children_to_process(&self, n: isize);
@ -354,6 +372,16 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
/// Returns true if the element has a CSS animation.
fn has_css_animations(&self, _pseudo: Option<&PseudoElement>) -> bool;
/// Returns true if the element has animation restyle hints.
fn has_animation_restyle_hints(&self) -> bool {
let data = match self.borrow_data() {
Some(d) => d,
None => return false,
};
return data.get_restyle()
.map_or(false, |r| r.hint.has_animation_hint());
}
}
/// TNode and TElement aren't Send because we want to be careful and explicit

View file

@ -42,6 +42,7 @@ use gecko_bindings::structs;
use gecko_bindings::structs::{RawGeckoElement, RawGeckoNode};
use gecko_bindings::structs::{nsIAtom, nsIContent, nsStyleContext};
use gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
use gecko_bindings::structs::NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
use gecko_bindings::sugar::ownership::HasArcFFI;
@ -510,6 +511,18 @@ impl<'le> TElement for GeckoElement<'le> {
self.unset_flags(NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
}
fn has_animation_only_dirty_descendants(&self) -> bool {
self.flags() & (NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32) != 0
}
unsafe fn set_animation_only_dirty_descendants(&self) {
self.set_flags(NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32)
}
unsafe fn unset_animation_only_dirty_descendants(&self) {
self.unset_flags(NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO as u32)
}
fn store_children_to_process(&self, _: isize) {
// This is only used for bottom-up traversal, and is thus a no-op for Gecko.
}

File diff suppressed because it is too large Load diff

View file

@ -1632,14 +1632,14 @@ pub mod root {
#[repr(C)]
#[derive(Debug)]
pub struct MutexImpl {
pub platformData_: [*mut ::std::os::raw::c_void; 8usize],
pub platformData_: [*mut ::std::os::raw::c_void; 5usize],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct MutexImpl_PlatformData([u8; 0]);
#[test]
fn bindgen_test_layout_MutexImpl() {
assert_eq!(::std::mem::size_of::<MutexImpl>() , 64usize ,
assert_eq!(::std::mem::size_of::<MutexImpl>() , 40usize ,
concat ! ( "Size of: " , stringify ! ( MutexImpl )
));
assert_eq! (::std::mem::align_of::<MutexImpl>() , 8usize ,
@ -2993,6 +2993,14 @@ pub mod root {
#[allow(unused_imports)]
use self::super::super::super::super::root;
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CSSStyleSheetParsingMode {
Author = 0,
User = 1,
Agent = 2,
EndGuard_ = 3,
}
#[repr(C)]
#[derive(Debug)]
pub struct OriginAttributesDictionary {
@ -3052,18 +3060,6 @@ pub mod root {
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Promise([u8; 0]);
pub mod workers {
#[allow(unused_imports)]
use self::super::super::super::super::root;
}
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CSSStyleSheetParsingMode {
Author = 0,
User = 1,
Agent = 2,
EndGuard_ = 3,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct CSSRuleList([u8; 0]);
@ -4774,92 +4770,6 @@ pub mod root {
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct EventListenerManager([u8; 0]);
/**
* BlockingResourceBase
* Base class of resources that might block clients trying to acquire them.
* Does debugging and deadlock detection in DEBUG builds.
**/
#[repr(C)]
#[derive(Debug)]
pub struct BlockingResourceBase {
pub _address: u8,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum BlockingResourceBase_BlockingResourceType {
eMutex = 0,
eReentrantMonitor = 1,
eCondVar = 2,
}
extern "C" {
#[link_name =
"_ZN7mozilla20BlockingResourceBase17kResourceTypeNameE"]
pub static mut BlockingResourceBase_kResourceTypeName:
[*const ::std::os::raw::c_char; 0usize];
}
#[test]
fn bindgen_test_layout_BlockingResourceBase() {
assert_eq!(::std::mem::size_of::<BlockingResourceBase>() , 1usize
, concat ! (
"Size of: " , stringify ! ( BlockingResourceBase ) ));
assert_eq! (::std::mem::align_of::<BlockingResourceBase>() ,
1usize , concat ! (
"Alignment of " , stringify ! ( BlockingResourceBase )
));
}
/**
* OffTheBooksMutex is identical to Mutex, except that OffTheBooksMutex doesn't
* include leak checking. Sometimes you want to intentionally "leak" a mutex
* until shutdown; in these cases, OffTheBooksMutex is for you.
*/
#[repr(C)]
#[derive(Debug)]
pub struct OffTheBooksMutex {
pub _base: root::mozilla::detail::MutexImpl,
}
#[test]
fn bindgen_test_layout_OffTheBooksMutex() {
assert_eq!(::std::mem::size_of::<OffTheBooksMutex>() , 64usize ,
concat ! (
"Size of: " , stringify ! ( OffTheBooksMutex ) ));
assert_eq! (::std::mem::align_of::<OffTheBooksMutex>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( OffTheBooksMutex ) ));
}
/**
* Mutex
* When possible, use MutexAutoLock/MutexAutoUnlock to lock/unlock this
* mutex within a scope, instead of calling Lock/Unlock directly.
*/
#[repr(C)]
#[derive(Debug)]
pub struct Mutex {
pub _base: root::mozilla::OffTheBooksMutex,
}
#[test]
fn bindgen_test_layout_Mutex() {
assert_eq!(::std::mem::size_of::<Mutex>() , 64usize , concat ! (
"Size of: " , stringify ! ( Mutex ) ));
assert_eq! (::std::mem::align_of::<Mutex>() , 8usize , concat ! (
"Alignment of " , stringify ! ( Mutex ) ));
}
pub mod net {
#[allow(unused_imports)]
use self::super::super::super::root;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ReferrerPolicy {
RP_No_Referrer = 2,
RP_Origin = 3,
RP_No_Referrer_When_Downgrade = 1,
RP_Origin_When_Crossorigin = 4,
RP_Unsafe_URL = 5,
RP_Same_Origin = 6,
RP_Strict_Origin = 7,
RP_Strict_Origin_When_Cross_Origin = 8,
RP_Unset = 0,
}
}
pub const FlushType_Frames: root::mozilla::FlushType =
FlushType::Style;
#[repr(u8)]
@ -5418,6 +5328,23 @@ pub mod root {
assert_eq! (::std::mem::align_of::<StyleSheet>() , 8usize , concat
! ( "Alignment of " , stringify ! ( StyleSheet ) ));
}
pub mod net {
#[allow(unused_imports)]
use self::super::super::super::root;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ReferrerPolicy {
RP_No_Referrer = 2,
RP_Origin = 3,
RP_No_Referrer_When_Downgrade = 1,
RP_Origin_When_Crossorigin = 4,
RP_Unsafe_URL = 5,
RP_Same_Origin = 6,
RP_Strict_Origin = 7,
RP_Strict_Origin_When_Cross_Origin = 8,
RP_Unset = 0,
}
}
#[repr(u8)]
/**
* Enumeration that represents one of the two supported style system backends.
@ -5530,7 +5457,7 @@ pub mod root {
eUseCounter_ImageBitmapRenderingContext_TransferImageBitmap = 86,
eUseCounter_URLCreateObjectURL_MediaStream = 87,
eUseCounter_XMLBaseAttribute = 88,
eUseCounter_XMLBaseAttributeWithStyledElement = 89,
eUseCounter_XMLBaseAttributeForStyleAttr = 89,
eUseCounter_Count = 90,
}
#[repr(u32)]
@ -6795,6 +6722,75 @@ pub mod root {
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct RestyleManager([u8; 0]);
/**
* BlockingResourceBase
* Base class of resources that might block clients trying to acquire them.
* Does debugging and deadlock detection in DEBUG builds.
**/
#[repr(C)]
#[derive(Debug)]
pub struct BlockingResourceBase {
pub _address: u8,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum BlockingResourceBase_BlockingResourceType {
eMutex = 0,
eReentrantMonitor = 1,
eCondVar = 2,
}
extern "C" {
#[link_name =
"_ZN7mozilla20BlockingResourceBase17kResourceTypeNameE"]
pub static mut BlockingResourceBase_kResourceTypeName:
[*const ::std::os::raw::c_char; 0usize];
}
#[test]
fn bindgen_test_layout_BlockingResourceBase() {
assert_eq!(::std::mem::size_of::<BlockingResourceBase>() , 1usize
, concat ! (
"Size of: " , stringify ! ( BlockingResourceBase ) ));
assert_eq! (::std::mem::align_of::<BlockingResourceBase>() ,
1usize , concat ! (
"Alignment of " , stringify ! ( BlockingResourceBase )
));
}
/**
* OffTheBooksMutex is identical to Mutex, except that OffTheBooksMutex doesn't
* include leak checking. Sometimes you want to intentionally "leak" a mutex
* until shutdown; in these cases, OffTheBooksMutex is for you.
*/
#[repr(C)]
#[derive(Debug)]
pub struct OffTheBooksMutex {
pub _base: root::mozilla::detail::MutexImpl,
}
#[test]
fn bindgen_test_layout_OffTheBooksMutex() {
assert_eq!(::std::mem::size_of::<OffTheBooksMutex>() , 40usize ,
concat ! (
"Size of: " , stringify ! ( OffTheBooksMutex ) ));
assert_eq! (::std::mem::align_of::<OffTheBooksMutex>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( OffTheBooksMutex ) ));
}
/**
* Mutex
* When possible, use MutexAutoLock/MutexAutoUnlock to lock/unlock this
* mutex within a scope, instead of calling Lock/Unlock directly.
*/
#[repr(C)]
#[derive(Debug)]
pub struct Mutex {
pub _base: root::mozilla::OffTheBooksMutex,
}
#[test]
fn bindgen_test_layout_Mutex() {
assert_eq!(::std::mem::size_of::<Mutex>() , 40usize , concat ! (
"Size of: " , stringify ! ( Mutex ) ));
assert_eq! (::std::mem::align_of::<Mutex>() , 8usize , concat ! (
"Alignment of " , stringify ! ( Mutex ) ));
}
pub mod image {
#[allow(unused_imports)]
use self::super::super::super::root;
@ -8185,12 +8181,6 @@ pub mod root {
pub type pair_first_type<_T1> = _T1;
pub type pair_second_type<_T2> = _T2;
#[repr(C)]
pub struct atomic<_Tp> {
pub _base: (),
pub _phantom_0: ::std::marker::PhantomData<_Tp>,
}
pub type atomic___base = [u8; 0usize];
#[repr(C)]
#[derive(Debug, Copy)]
pub struct input_iterator_tag {
pub _address: u8,
@ -8209,62 +8199,6 @@ pub mod root {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct forward_iterator_tag {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_forward_iterator_tag() {
assert_eq!(::std::mem::size_of::<forward_iterator_tag>() , 1usize
, concat ! (
"Size of: " , stringify ! ( forward_iterator_tag ) ));
assert_eq! (::std::mem::align_of::<forward_iterator_tag>() ,
1usize , concat ! (
"Alignment of " , stringify ! ( forward_iterator_tag )
));
}
impl Clone for forward_iterator_tag {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct bidirectional_iterator_tag {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_bidirectional_iterator_tag() {
assert_eq!(::std::mem::size_of::<bidirectional_iterator_tag>() ,
1usize , concat ! (
"Size of: " , stringify ! ( bidirectional_iterator_tag
) ));
assert_eq! (::std::mem::align_of::<bidirectional_iterator_tag>() ,
1usize , concat ! (
"Alignment of " , stringify ! (
bidirectional_iterator_tag ) ));
}
impl Clone for bidirectional_iterator_tag {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct random_access_iterator_tag {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_random_access_iterator_tag() {
assert_eq!(::std::mem::size_of::<random_access_iterator_tag>() ,
1usize , concat ! (
"Size of: " , stringify ! ( random_access_iterator_tag
) ));
assert_eq! (::std::mem::align_of::<random_access_iterator_tag>() ,
1usize , concat ! (
"Alignment of " , stringify ! (
random_access_iterator_tag ) ));
}
impl Clone for random_access_iterator_tag {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct iterator<_Category, _Tp, _Distance, _Pointer, _Reference> {
pub _address: u8,
@ -8274,22 +8208,22 @@ pub mod root {
pub _phantom_3: ::std::marker::PhantomData<_Pointer>,
pub _phantom_4: ::std::marker::PhantomData<_Reference>,
}
pub type iterator_iterator_category<_Category> = _Category;
pub type iterator_value_type<_Tp> = _Tp;
pub type iterator_difference_type<_Distance> = _Distance;
pub type iterator_pointer<_Pointer> = _Pointer;
pub type iterator_reference<_Reference> = _Reference;
pub type iterator_iterator_category<_Category> = _Category;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct __bit_const_reference<_Cp> {
pub __seg_: root::std::__bit_const_reference___storage_pointer<_Cp>,
pub __mask_: root::std::__bit_const_reference___storage_type<_Cp>,
#[derive(Debug)]
pub struct atomic<_Tp> {
pub _M_i: _Tp,
}
pub type __bit_const_reference___storage_type<_Cp> = _Cp;
pub type __bit_const_reference___storage_pointer<_Cp> = _Cp;
}
pub type __darwin_va_list = root::__builtin_va_list;
pub type va_list = root::__darwin_va_list;
pub mod __gnu_cxx {
#[allow(unused_imports)]
use self::super::super::root;
}
pub type va_list = root::__builtin_va_list;
/**
* MozRefCountType is Mozilla's reference count type.
*
@ -11754,7 +11688,7 @@ pub mod root {
eImageBitmapRenderingContext_TransferImageBitmap = 39,
eURLCreateObjectURL_MediaStream = 40,
eXMLBaseAttribute = 41,
eXMLBaseAttributeWithStyledElement = 42,
eXMLBaseAttributeForStyleAttr = 42,
eDeprecatedOperationCount = 43,
}
#[repr(u32)]
@ -12257,30 +12191,6 @@ pub mod root {
#[derive(Debug, Copy, Clone)]
pub struct nsISelection([u8; 0]);
#[repr(C)]
#[derive(Debug, Copy)]
pub struct mozIDOMWindowProxy {
pub _base: root::nsISupports,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct mozIDOMWindowProxy_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
#[test]
fn bindgen_test_layout_mozIDOMWindowProxy() {
assert_eq!(::std::mem::size_of::<mozIDOMWindowProxy>() , 8usize ,
concat ! ( "Size of: " , stringify ! ( mozIDOMWindowProxy )
));
assert_eq! (::std::mem::align_of::<mozIDOMWindowProxy>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( mozIDOMWindowProxy ) ));
}
impl Clone for mozIDOMWindowProxy {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug)]
pub struct nsPresContext {
pub _base: root::nsIObserver,
@ -13303,125 +13213,12 @@ pub mod root {
! ( "Alignment of " , stringify ! ( ErrorNote ) ));
}
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsIChannel {
pub _base: root::nsIRequest,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsIChannel_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
pub const nsIChannel_LOAD_DOCUMENT_URI: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_DOCUMENT_URI;
pub const nsIChannel_LOAD_RETARGETED_DOCUMENT_URI:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_RETARGETED_DOCUMENT_URI;
pub const nsIChannel_LOAD_REPLACE: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_REPLACE;
pub const nsIChannel_LOAD_INITIAL_DOCUMENT_URI:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_INITIAL_DOCUMENT_URI;
pub const nsIChannel_LOAD_TARGETED: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_TARGETED;
pub const nsIChannel_LOAD_CALL_CONTENT_SNIFFERS:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_CALL_CONTENT_SNIFFERS;
pub const nsIChannel_LOAD_CLASSIFY_URI: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_CLASSIFY_URI;
pub const nsIChannel_LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE;
pub const nsIChannel_LOAD_EXPLICIT_CREDENTIALS:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_EXPLICIT_CREDENTIALS;
pub const nsIChannel_LOAD_BYPASS_SERVICE_WORKER:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_BYPASS_SERVICE_WORKER;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsIChannel__bindgen_ty_1 {
LOAD_DOCUMENT_URI = 65536,
LOAD_RETARGETED_DOCUMENT_URI = 131072,
LOAD_REPLACE = 262144,
LOAD_INITIAL_DOCUMENT_URI = 524288,
LOAD_TARGETED = 1048576,
LOAD_CALL_CONTENT_SNIFFERS = 2097152,
LOAD_CLASSIFY_URI = 4194304,
LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE = 8388608,
LOAD_EXPLICIT_CREDENTIALS = 16777216,
LOAD_BYPASS_SERVICE_WORKER = 33554432,
}
pub const nsIChannel_DISPOSITION_INLINE: root::nsIChannel__bindgen_ty_2 =
nsIChannel__bindgen_ty_2::DISPOSITION_INLINE;
pub const nsIChannel_DISPOSITION_ATTACHMENT:
root::nsIChannel__bindgen_ty_2 =
nsIChannel__bindgen_ty_2::DISPOSITION_ATTACHMENT;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsIChannel__bindgen_ty_2 {
DISPOSITION_INLINE = 0,
DISPOSITION_ATTACHMENT = 1,
}
#[test]
fn bindgen_test_layout_nsIChannel() {
assert_eq!(::std::mem::size_of::<nsIChannel>() , 8usize , concat ! (
"Size of: " , stringify ! ( nsIChannel ) ));
assert_eq! (::std::mem::align_of::<nsIChannel>() , 8usize , concat ! (
"Alignment of " , stringify ! ( nsIChannel ) ));
}
impl Clone for nsIChannel {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsILoadContext {
pub _base: root::nsISupports,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsILoadContext_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
#[test]
fn bindgen_test_layout_nsILoadContext() {
assert_eq!(::std::mem::size_of::<nsILoadContext>() , 8usize , concat !
( "Size of: " , stringify ! ( nsILoadContext ) ));
assert_eq! (::std::mem::align_of::<nsILoadContext>() , 8usize , concat
! ( "Alignment of " , stringify ! ( nsILoadContext ) ));
}
impl Clone for nsILoadContext {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsIInterfaceRequestor {
pub _base: root::nsISupports,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsIInterfaceRequestor_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
#[test]
fn bindgen_test_layout_nsIInterfaceRequestor() {
assert_eq!(::std::mem::size_of::<nsIInterfaceRequestor>() , 8usize ,
concat ! (
"Size of: " , stringify ! ( nsIInterfaceRequestor ) ));
assert_eq! (::std::mem::align_of::<nsIInterfaceRequestor>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( nsIInterfaceRequestor )
));
}
impl Clone for nsIInterfaceRequestor {
fn clone(&self) -> Self { *self }
pub enum nsCompatibility {
eCompatibility_FullStandards = 1,
eCompatibility_AlmostStandards = 2,
eCompatibility_NavQuirks = 3,
}
#[repr(C)]
#[derive(Debug, Copy)]
@ -13770,6 +13567,82 @@ pub mod root {
"Alignment of field: " , stringify ! ( nsINode ) , "::" ,
stringify ! ( mSlots ) ));
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsIChannel {
pub _base: root::nsIRequest,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsIChannel_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
pub const nsIChannel_LOAD_DOCUMENT_URI: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_DOCUMENT_URI;
pub const nsIChannel_LOAD_RETARGETED_DOCUMENT_URI:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_RETARGETED_DOCUMENT_URI;
pub const nsIChannel_LOAD_REPLACE: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_REPLACE;
pub const nsIChannel_LOAD_INITIAL_DOCUMENT_URI:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_INITIAL_DOCUMENT_URI;
pub const nsIChannel_LOAD_TARGETED: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_TARGETED;
pub const nsIChannel_LOAD_CALL_CONTENT_SNIFFERS:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_CALL_CONTENT_SNIFFERS;
pub const nsIChannel_LOAD_CLASSIFY_URI: root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_CLASSIFY_URI;
pub const nsIChannel_LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE;
pub const nsIChannel_LOAD_EXPLICIT_CREDENTIALS:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_EXPLICIT_CREDENTIALS;
pub const nsIChannel_LOAD_BYPASS_SERVICE_WORKER:
root::nsIChannel__bindgen_ty_1 =
nsIChannel__bindgen_ty_1::LOAD_BYPASS_SERVICE_WORKER;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsIChannel__bindgen_ty_1 {
LOAD_DOCUMENT_URI = 65536,
LOAD_RETARGETED_DOCUMENT_URI = 131072,
LOAD_REPLACE = 262144,
LOAD_INITIAL_DOCUMENT_URI = 524288,
LOAD_TARGETED = 1048576,
LOAD_CALL_CONTENT_SNIFFERS = 2097152,
LOAD_CLASSIFY_URI = 4194304,
LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE = 8388608,
LOAD_EXPLICIT_CREDENTIALS = 16777216,
LOAD_BYPASS_SERVICE_WORKER = 33554432,
}
pub const nsIChannel_DISPOSITION_INLINE: root::nsIChannel__bindgen_ty_2 =
nsIChannel__bindgen_ty_2::DISPOSITION_INLINE;
pub const nsIChannel_DISPOSITION_ATTACHMENT:
root::nsIChannel__bindgen_ty_2 =
nsIChannel__bindgen_ty_2::DISPOSITION_ATTACHMENT;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsIChannel__bindgen_ty_2 {
DISPOSITION_INLINE = 0,
DISPOSITION_ATTACHMENT = 1,
}
#[test]
fn bindgen_test_layout_nsIChannel() {
assert_eq!(::std::mem::size_of::<nsIChannel>() , 8usize , concat ! (
"Size of: " , stringify ! ( nsIChannel ) ));
assert_eq! (::std::mem::align_of::<nsIChannel>() , 8usize , concat ! (
"Alignment of " , stringify ! ( nsIChannel ) ));
}
impl Clone for nsIChannel {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsILoadContext([u8; 0]);
pub type nsSecurityFlags = u32;
#[repr(C)]
#[derive(Debug, Copy)]
@ -13878,6 +13751,31 @@ pub mod root {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsIInterfaceRequestor {
pub _base: root::nsISupports,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsIInterfaceRequestor_COMTypeInfo<T, U> {
pub _address: u8,
pub _phantom_0: ::std::marker::PhantomData<T>,
pub _phantom_1: ::std::marker::PhantomData<U>,
}
#[test]
fn bindgen_test_layout_nsIInterfaceRequestor() {
assert_eq!(::std::mem::size_of::<nsIInterfaceRequestor>() , 8usize ,
concat ! (
"Size of: " , stringify ! ( nsIInterfaceRequestor ) ));
assert_eq! (::std::mem::align_of::<nsIInterfaceRequestor>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( nsIInterfaceRequestor )
));
}
impl Clone for nsIInterfaceRequestor {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsIInputStream([u8; 0]);
#[repr(C)]
@ -13904,13 +13802,6 @@ pub mod root {
impl Clone for nsIStreamListener {
fn clone(&self) -> Self { *self }
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsCompatibility {
eCompatibility_FullStandards = 1,
eCompatibility_AlmostStandards = 2,
eCompatibility_NavQuirks = 3,
}
#[repr(C)]
#[derive(Debug)]
pub struct nsAttrValue {
@ -15159,63 +15050,66 @@ pub mod root {
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct nsDOMMutationObserver([u8; 0]);
pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_LISTENERMANAGER;
pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_PROPERTIES;
pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_ANONYMOUS_ROOT;
pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS_ROOT;
pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_FORCE_XBL_BINDINGS;
pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_MAY_BE_IN_BINDING_MNGR;
pub const NODE_IS_EDITABLE: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_EDITABLE;
pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_NATIVE_ANONYMOUS;
pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_IN_SHADOW_TREE;
pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_EMPTY_SELECTOR;
pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_SLOW_SELECTOR;
pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_EDGE_CHILD_SELECTOR;
pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS;
pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_ALL_SELECTOR_FLAGS;
pub const NODE_NEEDS_FRAME: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_NEEDS_FRAME;
pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_DESCENDANTS_NEED_FRAMES;
pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_ACCESSKEY;
pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_DIRECTION_RTL;
pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_HAS_DIRECTION_LTR;
pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_ALL_DIRECTION_FLAGS;
pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_CHROME_ONLY_ACCESS;
pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS;
pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1;
pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_2;
pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_SHARED_RESTYLE_BIT_1;
pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_28 =
_bindgen_ty_28::NODE_TYPE_SPECIFIC_BITS_OFFSET;
pub const NODE_HAS_LISTENERMANAGER: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_LISTENERMANAGER;
pub const NODE_HAS_PROPERTIES: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_PROPERTIES;
pub const NODE_IS_ANONYMOUS_ROOT: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_ANONYMOUS_ROOT;
pub const NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
pub const NODE_IS_NATIVE_ANONYMOUS_ROOT: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_NATIVE_ANONYMOUS_ROOT;
pub const NODE_FORCE_XBL_BINDINGS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_FORCE_XBL_BINDINGS;
pub const NODE_MAY_BE_IN_BINDING_MNGR: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_MAY_BE_IN_BINDING_MNGR;
pub const NODE_IS_EDITABLE: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_EDITABLE;
pub const NODE_IS_NATIVE_ANONYMOUS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_NATIVE_ANONYMOUS;
pub const NODE_IS_IN_SHADOW_TREE: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_IN_SHADOW_TREE;
pub const NODE_HAS_EMPTY_SELECTOR: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_EMPTY_SELECTOR;
pub const NODE_HAS_SLOW_SELECTOR: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_SLOW_SELECTOR;
pub const NODE_HAS_EDGE_CHILD_SELECTOR: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_EDGE_CHILD_SELECTOR;
pub const NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS;
pub const NODE_ALL_SELECTOR_FLAGS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_ALL_SELECTOR_FLAGS;
pub const NODE_NEEDS_FRAME: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_NEEDS_FRAME;
pub const NODE_DESCENDANTS_NEED_FRAMES: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_DESCENDANTS_NEED_FRAMES;
pub const NODE_HAS_ACCESSKEY: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_ACCESSKEY;
pub const NODE_HAS_DIRECTION_RTL: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_DIRECTION_RTL;
pub const NODE_HAS_DIRECTION_LTR: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_HAS_DIRECTION_LTR;
pub const NODE_ALL_DIRECTION_FLAGS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_ALL_DIRECTION_FLAGS;
pub const NODE_CHROME_ONLY_ACCESS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_CHROME_ONLY_ACCESS;
pub const NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_IS_ROOT_OF_CHROME_ONLY_ACCESS;
pub const NODE_SHARED_RESTYLE_BIT_1: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_1;
pub const NODE_SHARED_RESTYLE_BIT_2: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_2;
pub const NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_1;
pub const NODE_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO:
root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_SHARED_RESTYLE_BIT_2;
pub const NODE_TYPE_SPECIFIC_BITS_OFFSET: root::_bindgen_ty_105 =
_bindgen_ty_105::NODE_TYPE_SPECIFIC_BITS_OFFSET;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_28 {
pub enum _bindgen_ty_105 {
NODE_HAS_LISTENERMANAGER = 4,
NODE_HAS_PROPERTIES = 8,
NODE_IS_ANONYMOUS_ROOT = 16,
@ -22096,7 +21990,7 @@ pub mod root {
pub type imgRequest_HasThreadSafeRefCnt = root::mozilla::TrueType;
#[test]
fn bindgen_test_layout_imgRequest() {
assert_eq!(::std::mem::size_of::<imgRequest>() , 400usize , concat ! (
assert_eq!(::std::mem::size_of::<imgRequest>() , 376usize , concat ! (
"Size of: " , stringify ! ( imgRequest ) ));
assert_eq! (::std::mem::align_of::<imgRequest>() , 8usize , concat ! (
"Alignment of " , stringify ! ( imgRequest ) ));

View file

@ -17,7 +17,7 @@ use data::{ComputedStyle, ElementData, ElementStyles, RestyleData};
use dom::{AnimationRules, SendElement, TElement, TNode};
use properties::{CascadeFlags, ComputedValues, SHAREABLE, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
use properties::longhands::display::computed_value as display;
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RestyleHint};
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RESTYLE_CSS_ANIMATIONS, RestyleHint};
use rule_tree::{CascadeLevel, RuleTree, StrongRuleNode};
use selector_parser::{PseudoElement, RestyleDamage, SelectorImpl};
use selectors::MatchAttr;
@ -954,30 +954,54 @@ pub trait MatchMethods : TElement {
context: &StyleContext<Self>,
data: &mut AtomicRefMut<ElementData>)
-> bool {
let primary_rules = &mut data.styles_mut().primary.rules;
use properties::PropertyDeclarationBlock;
use shared_lock::Locked;
let element_styles = &mut data.styles_mut();
let primary_rules = &mut element_styles.primary.rules;
let mut rule_node_changed = false;
if hint.contains(RESTYLE_STYLE_ATTRIBUTE) {
let style_attribute = self.style_attribute();
{
let mut replace_rule_node = |level: CascadeLevel,
pdb: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
path: &mut StrongRuleNode| {
let new_node = context.shared.stylist.rule_tree
.update_rule_at_level(level, pdb, path, &context.shared.guards);
if let Some(n) = new_node {
*path = n;
rule_node_changed = true;
}
};
let new_node = context.shared.stylist.rule_tree
.update_rule_at_level(CascadeLevel::StyleAttributeNormal,
style_attribute,
primary_rules,
&context.shared.guards);
if let Some(n) = new_node {
*primary_rules = n;
rule_node_changed = true;
}
// RESTYLE_CSS_ANIMATIONS is processed prior to other restyle hints
// in the name of animation-only traversal. Rest of restyle hints
// will be processed in a subsequent normal traversal.
if hint.contains(RESTYLE_CSS_ANIMATIONS) {
debug_assert!(context.shared.animation_only_restyle);
let new_node = context.shared.stylist.rule_tree
.update_rule_at_level(CascadeLevel::StyleAttributeImportant,
style_attribute,
primary_rules,
&context.shared.guards);
if let Some(n) = new_node {
*primary_rules = n;
rule_node_changed = true;
let animation_rule = self.get_animation_rule(None);
replace_rule_node(CascadeLevel::Animations,
animation_rule.as_ref(),
primary_rules);
let iter = element_styles.pseudos.iter_mut().filter(|&(p, _)|
<Self as MatchAttr>::Impl::pseudo_is_before_or_after(p));
for (pseudo, ref mut computed) in iter {
let animation_rule = self.get_animation_rule(Some(pseudo));
let pseudo_rules = &mut computed.rules;
replace_rule_node(CascadeLevel::Animations,
animation_rule.as_ref(),
pseudo_rules);
}
} else if hint.contains(RESTYLE_STYLE_ATTRIBUTE) {
let style_attribute = self.style_attribute();
replace_rule_node(CascadeLevel::StyleAttributeNormal,
style_attribute,
primary_rules);
replace_rule_node(CascadeLevel::StyleAttributeImportant,
style_attribute,
primary_rules);
// The per-pseudo rule nodes never change in this path.
}
}

View file

@ -47,6 +47,11 @@ bitflags! {
/// of their descendants.
const RESTYLE_LATER_SIBLINGS = 0x08,
/// Replace the style data coming from CSS animations without updating
/// any other style data. This hint is only processed in animation-only
/// traversal which is prior to normal traversal.
const RESTYLE_CSS_ANIMATIONS = 0x20,
/// Don't re-run selector-matching on the element, only the style
/// attribute has changed, and this change didn't have any other
/// dependencies.
@ -81,6 +86,7 @@ pub fn assert_restyle_hints_match() {
// (RESTYLE_SELF | RESTYLE_DESCENDANTS).
nsRestyleHint_eRestyle_Subtree => RESTYLE_DESCENDANTS,
nsRestyleHint_eRestyle_LaterSiblings => RESTYLE_LATER_SIBLINGS,
nsRestyleHint_eRestyle_CSSAnimations => RESTYLE_CSS_ANIMATIONS,
nsRestyleHint_eRestyle_StyleAttribute => RESTYLE_STYLE_ATTRIBUTE,
}
}
@ -89,7 +95,7 @@ impl RestyleHint {
/// The subset hints that affect the styling of a single element during the
/// traversal.
pub fn for_self() -> Self {
RESTYLE_SELF | RESTYLE_STYLE_ATTRIBUTE
RESTYLE_SELF | RESTYLE_STYLE_ATTRIBUTE | RESTYLE_CSS_ANIMATIONS
}
}

View file

@ -31,6 +31,28 @@ pub struct PerLevelTraversalData {
pub current_dom_depth: Option<usize>,
}
bitflags! {
/// Represents that target elements of the traversal.
pub flags TraversalFlags: u8 {
/// Traverse only unstyled children.
const UNSTYLED_CHILDREN_ONLY = 0x01,
/// Traverse only elements for animation restyles
const ANIMATION_ONLY = 0x02,
}
}
impl TraversalFlags {
/// Returns true if the traversal is for animation-only restyles.
pub fn for_animation_only(&self) -> bool {
self.contains(ANIMATION_ONLY)
}
/// Returns true if the traversal is for unstyled children.
pub fn for_unstyled_children_only(&self) -> bool {
self.contains(UNSTYLED_CHILDREN_ONLY)
}
}
/// This structure exists to enforce that callers invoke pre_traverse, and also
/// to pass information from the pre-traversal into the primary traversal.
pub struct PreTraverseToken {
@ -109,12 +131,15 @@ pub trait DomTraversal<E: TElement> : Sync {
/// a traversal is needed. Returns a token that allows the caller to prove
/// that the call happened.
///
/// The unstyled_children_only parameter is used in Gecko to style newly-
/// The traversal_flag is used in Gecko.
/// If traversal_flag::UNSTYLED_CHILDREN_ONLY is specified, style newly-
/// appended children without restyling the parent.
fn pre_traverse(root: E, stylist: &Stylist, unstyled_children_only: bool)
/// If traversal_flag::ANIMATION_ONLY is specified, style only elements for
/// animations.
fn pre_traverse(root: E, stylist: &Stylist, traversal_flags: TraversalFlags)
-> PreTraverseToken
{
if unstyled_children_only {
if traversal_flags.for_unstyled_children_only() {
return PreTraverseToken {
traverse: true,
unstyled_children_only: true,
@ -135,7 +160,7 @@ pub trait DomTraversal<E: TElement> : Sync {
}
PreTraverseToken {
traverse: Self::node_needs_traversal(root.as_node()),
traverse: Self::node_needs_traversal(root.as_node(), traversal_flags.for_animation_only()),
unstyled_children_only: false,
}
}
@ -149,7 +174,7 @@ pub trait DomTraversal<E: TElement> : Sync {
}
/// Returns true if traversal is needed for the given node and subtree.
fn node_needs_traversal(node: E::ConcreteNode) -> bool {
fn node_needs_traversal(node: E::ConcreteNode, animation_only: bool) -> bool {
// Non-incremental layout visits every node.
if cfg!(feature = "servo") && opts::get().nonincremental_layout {
return true;
@ -158,6 +183,22 @@ pub trait DomTraversal<E: TElement> : Sync {
match node.as_element() {
None => Self::text_node_needs_traversal(node),
Some(el) => {
// In case of animation-only traversal we need to traverse
// the element if the element has animation only dirty
// descendants bit, animation-only restyle hint or recascade.
if animation_only {
if el.has_animation_only_dirty_descendants() {
return true;
}
let data = match el.borrow_data() {
Some(d) => d,
None => return false,
};
return data.get_restyle()
.map_or(false, |r| r.hint.has_animation_hint() || r.recascade);
}
// If the dirty descendants bit is set, we need to traverse no
// matter what. Skip examining the ElementData.
if el.has_dirty_descendants() {
@ -270,7 +311,7 @@ pub trait DomTraversal<E: TElement> : Sync {
}
for kid in parent.as_node().children() {
if Self::node_needs_traversal(kid) {
if Self::node_needs_traversal(kid, self.shared_context().animation_only_restyle) {
let el = kid.as_element();
if el.as_ref().and_then(|el| el.borrow_data())
.map_or(false, |d| d.has_styles())
@ -448,21 +489,38 @@ pub fn recalc_style_at<E, D>(traversal: &D,
None => empty_hint,
Some(r) => {
r.recascade = false;
mem::replace(&mut r.hint, empty_hint).propagate()
if r.hint.has_animation_hint() {
debug_assert!(context.shared.animation_only_restyle,
"animation restyle hint should be handled during animation-only restyles");
// Drop animation restyle hint.
let propagated_hint = r.hint.propagate();
r.hint.remove_animation_hint();
propagated_hint
} else {
mem::replace(&mut r.hint, empty_hint).propagate()
}
},
};
debug_assert!(data.has_current_styles());
debug_assert!(data.has_current_styles() || context.shared.animation_only_restyle,
"Should have computed style or haven't yet valid computed style in case of animation-only restyle");
trace!("propagated_hint={:?}, inherited_style_changed={:?}", propagated_hint, inherited_style_changed);
// Preprocess children, propagating restyle hints and handling sibling relationships.
if traversal.should_traverse_children(&mut context.thread_local, element, &data, DontLog) &&
(element.has_dirty_descendants() || !propagated_hint.is_empty() || inherited_style_changed) {
((!context.shared.animation_only_restyle && element.has_dirty_descendants()) ||
(context.shared.animation_only_restyle && element.has_animation_only_dirty_descendants()) ||
!propagated_hint.is_empty() ||
inherited_style_changed) {
let damage_handled = data.get_restyle().map_or(RestyleDamage::empty(), |r| {
r.damage_handled() | r.damage.handled_for_descendants()
});
preprocess_children(traversal, element, propagated_hint, damage_handled, inherited_style_changed);
}
if context.shared.animation_only_restyle {
unsafe { element.unset_animation_only_dirty_descendants(); }
}
// Make sure the dirty descendants bit is not set for the root of a
// display:none subtree, even if the style didn't change (since, if
// the style did change, we'd have already cleared it above).

View file

@ -83,7 +83,8 @@ use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::supports::parse_condition_or_declaration;
use style::thread_state;
use style::timer::Timer;
use style::traversal::{resolve_style, DomTraversal, TraversalDriver};
use style::traversal::{ANIMATION_ONLY, UNSTYLED_CHILDREN_ONLY};
use style::traversal::{resolve_style, DomTraversal, TraversalDriver, TraversalFlags};
use style_traits::ToCss;
use super::stylesheet_loader::StylesheetLoader;
@ -124,7 +125,8 @@ pub extern "C" fn Servo_Shutdown() {
}
fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard,
per_doc_data: &PerDocumentStyleDataImpl) -> SharedStyleContext<'a> {
per_doc_data: &PerDocumentStyleDataImpl,
animation_only: bool) -> SharedStyleContext<'a> {
let local_context_data =
ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
@ -139,11 +141,12 @@ fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard,
timer: Timer::new(),
// FIXME Find the real QuirksMode information for this document
quirks_mode: QuirksMode::NoQuirks,
animation_only_restyle: animation_only,
}
}
fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
unstyled_children_only: bool) {
traversal_flags: TraversalFlags) {
// When new content is inserted in a display:none subtree, we will call into
// servo to try to style it. Detect that here and bail out.
if let Some(parent) = element.parent_element() {
@ -155,7 +158,7 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
let token = RecalcStyleOnly::pre_traverse(element, &per_doc_data.stylist, unstyled_children_only);
let token = RecalcStyleOnly::pre_traverse(element, &per_doc_data.stylist, traversal_flags);
if !token.should_traverse() {
return;
}
@ -165,7 +168,8 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
let global_style_data = &*GLOBAL_STYLE_DATA;
let guard = global_style_data.shared_lock.read();
let shared_style_context = create_shared_context(&guard, &per_doc_data);
let shared_style_context = create_shared_context(&guard, &per_doc_data,
traversal_flags.for_animation_only());
let traversal_driver = if global_style_data.style_thread_pool.is_none() {
TraversalDriver::Sequential
@ -192,8 +196,18 @@ pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed,
behavior: structs::TraversalRootBehavior) -> bool {
let element = GeckoElement(root);
debug!("Servo_TraverseSubtree: {:?}", element);
traverse_subtree(element, raw_data,
behavior == structs::TraversalRootBehavior::UnstyledChildrenOnly);
let traversal_flags = match behavior {
structs::TraversalRootBehavior::UnstyledChildrenOnly => UNSTYLED_CHILDREN_ONLY,
_ => TraversalFlags::empty(),
};
if element.has_animation_only_dirty_descendants() ||
element.has_animation_restyle_hints() {
traverse_subtree(element, raw_data, traversal_flags | ANIMATION_ONLY);
}
traverse_subtree(element, raw_data, traversal_flags);
element.has_dirty_descendants() || element.mutate_data().unwrap().has_restyle()
}
@ -1359,7 +1373,9 @@ pub extern "C" fn Servo_CSSSupports(cond: *const nsACString) -> bool {
/// Only safe to call on the main thread, with exclusive access to the element and
/// its ancestors.
unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>, element: GeckoElement)
unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>,
element: GeckoElement,
animation_only: bool)
-> Option<&'a mut RestyleData>
{
// Don't generate a useless RestyleData if the element hasn't been styled.
@ -1371,8 +1387,13 @@ unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>, element: Ge
let mut curr = element;
while let Some(parent) = curr.parent_element() {
curr = parent;
if curr.has_dirty_descendants() { break; }
curr.set_dirty_descendants();
if animation_only {
if curr.has_animation_only_dirty_descendants() { break; }
curr.set_animation_only_dirty_descendants();
} else {
if curr.has_dirty_descendants() { break; }
curr.set_dirty_descendants();
}
}
bindings::Gecko_SetOwnerDocumentNeedsStyleFlush(element.0);
@ -1387,7 +1408,7 @@ pub extern "C" fn Servo_Element_GetSnapshot(element: RawGeckoElementBorrowed) ->
let snapshot = match element.mutate_data() {
None => ptr::null_mut(),
Some(mut data) => {
if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element) } {
if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element, false) } {
restyle_data.snapshot.ensure(|| element.create_snapshot()).borrow_mut_raw()
} else {
ptr::null_mut()
@ -1407,10 +1428,14 @@ pub extern "C" fn Servo_NoteExplicitHints(element: RawGeckoElementBorrowed,
let damage = GeckoRestyleDamage::new(change_hint);
debug!("Servo_NoteExplicitHints: {:?}, restyle_hint={:?}, change_hint={:?}",
element, restyle_hint, change_hint);
debug_assert!(restyle_hint == structs::nsRestyleHint_eRestyle_CSSAnimations ||
(restyle_hint.0 & structs::nsRestyleHint_eRestyle_CSSAnimations.0) == 0,
"eRestyle_CSSAnimations should only appear by itself");
let mut maybe_data = element.mutate_data();
let maybe_restyle_data =
maybe_data.as_mut().and_then(|d| unsafe { maybe_restyle(d, element) });
let maybe_restyle_data = maybe_data.as_mut().and_then(|d| unsafe {
maybe_restyle(d, element, restyle_hint == structs::nsRestyleHint_eRestyle_CSSAnimations)
});
if let Some(restyle_data) = maybe_restyle_data {
let restyle_hint: RestyleHint = restyle_hint.into();
restyle_data.hint.insert(&restyle_hint.into());
@ -1492,7 +1517,7 @@ pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
}
// We don't have the style ready. Go ahead and compute it as necessary.
let shared = create_shared_context(&guard, &mut doc_data.borrow_mut());
let shared = create_shared_context(&guard, &mut doc_data.borrow_mut(), false);
let mut tlc = ThreadLocalStyleContext::new(&shared);
let mut context = StyleContext {
shared: &shared,
@ -1592,7 +1617,7 @@ pub extern "C" fn Servo_AssertTreeIsClean(root: RawGeckoElementBorrowed) {
let root = GeckoElement(root);
fn assert_subtree_is_clean<'le>(el: GeckoElement<'le>) {
debug_assert!(!el.has_dirty_descendants());
debug_assert!(!el.has_dirty_descendants() && !el.has_animation_only_dirty_descendants());
for child in el.as_node().children() {
if let Some(child) = child.as_element() {
assert_subtree_is_clean(child);