Bug 1370358 - Log element during selector matching. r=emilio
MozReview-Commit-ID: D8eFyRCy5BR
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -2513,16 +2513,17 @@ dependencies = [
[[package]]
name = "selectors"
version = "0.19.0"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"precomputed-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"size_of_test 0.0.1",
"smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
--- a/servo/components/script/dom/element.rs
+++ b/servo/components/script/dom/element.rs
@@ -146,16 +146,22 @@ impl fmt::Debug for Element {
try!(write!(f, "<{}", self.local_name));
if let Some(ref id) = *self.id_attribute.borrow() {
try!(write!(f, " id={}", id));
}
write!(f, ">")
}
}
+impl fmt::Debug for Root<Element> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ (**self).fmt(f)
+ }
+}
+
#[derive(PartialEq, HeapSizeOf)]
pub enum ElementCreator {
ParserCreated(u64),
ScriptCreated,
}
impl ElementCreator {
pub fn is_parser_created(&self) -> bool {
--- a/servo/components/selectors/Cargo.toml
+++ b/servo/components/selectors/Cargo.toml
@@ -20,16 +20,17 @@ doctest = false
[features]
gecko_like_types = []
[dependencies]
bitflags = "0.7"
matches = "0.1"
cssparser = "0.13.7"
+log = "0.3"
fnv = "1.0"
phf = "0.7.18"
precomputed-hash = "0.1"
smallvec = "0.3"
[dev-dependencies]
size_of_test = {path = "../size_of_test"}
--- a/servo/components/selectors/lib.rs
+++ b/servo/components/selectors/lib.rs
@@ -1,14 +1,15 @@
/* 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/. */
#[macro_use] extern crate bitflags;
#[macro_use] extern crate cssparser;
+#[macro_use] extern crate log;
#[macro_use] extern crate matches;
extern crate fnv;
extern crate phf;
extern crate precomputed_hash;
#[cfg(test)] #[macro_use] extern crate size_of_test;
extern crate smallvec;
pub mod arcslice;
--- a/servo/components/selectors/matching.rs
+++ b/servo/components/selectors/matching.rs
@@ -190,17 +190,17 @@ fn may_match<E>(sel: &SelectorInner<E::I
/// complex selector. A "relevant link" is the element being matched if it is a
/// link or the nearest ancestor link.
///
/// `matches_complex_selector` creates a new instance of this for each complex
/// selector we try to match for an element. This is done because `is_visited`
/// and `is_unvisited` are based on relevant link state of only the current
/// complex selector being matched (not the global relevant link status for all
/// selectors in `MatchingContext`).
-#[derive(PartialEq, Eq, Copy, Clone)]
+#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum RelevantLinkStatus {
/// Looking for a possible relevant link. This is the initial mode when
/// matching a selector.
Looking,
/// Not looking for a relevant link. We transition to this mode if we
/// encounter a sibiling combinator (since only ancestor combinators are
/// allowed for this purpose).
NotLooking,
@@ -408,16 +408,19 @@ fn matches_complex_selector_internal<E,
F: FnMut(&E, ElementSelectorFlags),
{
let mut relevant_link = relevant_link.examine_potential_link(element, context);
let matches_all_simple_selectors = selector_iter.all(|simple| {
matches_simple_selector(simple, element, context, &relevant_link, flags_setter)
});
+ debug!("Matching for {:?}, simple selector {:?}, relevant link {:?}",
+ element, selector_iter, relevant_link);
+
let combinator = selector_iter.next_sequence();
let siblings = combinator.map_or(false, |c| c.is_sibling());
if siblings {
flags_setter(element, HAS_SLOW_SELECTOR_LATER_SIBLINGS);
}
if !matches_all_simple_selectors {
return SelectorMatchingResult::NotMatchedAndRestartFromClosestLaterSibling;
--- a/servo/components/selectors/parser.rs
+++ b/servo/components/selectors/parser.rs
@@ -449,16 +449,26 @@ impl<'a, Impl: SelectorImpl> Iterator fo
self.next_combinator = Some(c);
None
},
Some(x) => Some(x),
}
}
}
+impl<'a, Impl: SelectorImpl> fmt::Debug for SelectorIter<'a, Impl> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let iter = self.iter.clone().rev();
+ for component in iter {
+ component.to_css(f)?
+ }
+ Ok(())
+ }
+}
+
/// An iterator over all simple selectors belonging to ancestors.
pub struct AncestorIter<'a, Impl: 'a + SelectorImpl>(SelectorIter<'a, Impl>);
impl<'a, Impl: 'a + SelectorImpl> AncestorIter<'a, Impl> {
/// Creates an AncestorIter. The passed-in iterator is assumed to point to
/// the beginning of the child sequence, which will be skipped.
fn new(inner: SelectorIter<'a, Impl>) -> Self {
let mut result = AncestorIter(inner);
result.skip_until_ancestor();
--- a/servo/components/selectors/tree.rs
+++ b/servo/components/selectors/tree.rs
@@ -3,18 +3,19 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Traits that nodes must implement. Breaks the otherwise-cyclic dependency
//! between layout and style.
use attr::{AttrSelectorOperation, NamespaceConstraint};
use matching::{ElementSelectorFlags, MatchingContext, RelevantLinkStatus};
use parser::SelectorImpl;
+use std::fmt::Debug;
-pub trait Element: Sized {
+pub trait Element: Sized + Debug {
type Impl: SelectorImpl;
fn parent_element(&self) -> Option<Self>;
/// The parent of a given pseudo-element, after matching a pseudo-element
/// selector.
///
/// This is guaranteed to be called in a pseudo-element.
--- a/servo/components/style/restyle_hints.rs
+++ b/servo/components/style/restyle_hints.rs
@@ -23,16 +23,17 @@ use selectors::attr::{AttrSelectorOperat
use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode};
use selectors::matching::{RelevantLinkStatus, VisitedHandlingMode, matches_selector};
use selectors::parser::{Combinator, Component, Selector, SelectorInner, SelectorMethods};
use selectors::visitor::SelectorVisitor;
use smallvec::SmallVec;
use std::cell::Cell;
use std::clone::Clone;
use std::cmp;
+use std::fmt;
/// When the ElementState of an element (like IN_HOVER_STATE) changes,
/// certain pseudo-classes (like :hover) may require us to restyle that
/// element, its siblings, and/or its descendants. Similarly, when various
/// attributes of an element change, we may also need to restyle things with
/// id, class, and attribute selectors. Doing this conservatively is
/// expensive, and so we use RestyleHints to short-circuit work we know is
/// unnecessary.
@@ -601,16 +602,25 @@ impl<'a, E> ElementWrapper<'a, E>
match snapshot.state() {
Some(state) => state ^ self.element.get_state(),
None => ElementState::empty(),
}
}
}
+impl<'a, E> fmt::Debug for ElementWrapper<'a, E>
+ where E: TElement,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ // Ignore other fields for now, can change later if needed.
+ self.element.fmt(f)
+ }
+}
+
#[cfg(feature = "gecko")]
fn dir_selector_to_state(s: &[u16]) -> ElementState {
// Jump through some hoops to deal with our Box<[u16]> thing.
const LTR: [u16; 4] = [b'l' as u16, b't' as u16, b'r' as u16, 0];
const RTL: [u16; 4] = [b'r' as u16, b't' as u16, b'l' as u16, 0];
if LTR == *s {
IN_LTR_STATE
} else if RTL == *s {