Bug 1370358 - Log element during selector matching. r=emilio draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Tue, 06 Jun 2017 16:36:25 -0500
changeset 589820 787661f9033fbc08337641f3b8e363c77cd8cffa
parent 589819 b0f7eea3760c16236a6ba255258940676e0812dd
child 589821 a8dda4cabce71851d42222b59996ac58b72e2a21
push id62533
push userbmo:jryans@gmail.com
push dateTue, 06 Jun 2017 22:27:16 +0000
reviewersemilio
bugs1370358
milestone55.0a1
Bug 1370358 - Log element during selector matching. r=emilio MozReview-Commit-ID: D8eFyRCy5BR
servo/Cargo.lock
servo/components/script/dom/element.rs
servo/components/selectors/Cargo.toml
servo/components/selectors/lib.rs
servo/components/selectors/matching.rs
servo/components/selectors/parser.rs
servo/components/selectors/tree.rs
servo/components/style/restyle_hints.rs
--- 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 {