servo: Merge #18790 - Support :scope pseudo-class (from upsuper:scope); r=emilio

This fixes [bug 1406817](https://bugzilla.mozilla.org/show_bug.cgi?id=1406817).

Source-Repo: https://github.com/servo/servo
Source-Revision: bbb2a3cde9f4c7fc9debd5784fce2b07966101ff

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : d4d2b23cd7a27ea3fc053d5062673ff19f6c2a11
This commit is contained in:
Xidorn Quan 2017-10-09 23:04:15 -05:00
parent 52c9629669
commit 0aa342687d
6 changed files with 33 additions and 3 deletions

View File

@ -87,6 +87,7 @@ use net_traits::request::CorsSettings;
use ref_filter_map::ref_filter_map;
use script_layout_interface::message::ReflowGoal;
use script_thread::ScriptThread;
use selectors::Element as SelectorsElement;
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity};
use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, MatchingMode};
use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS};
@ -2191,10 +2192,12 @@ impl ElementMethods for Element {
Err(_) => Err(Error::Syntax),
Ok(selectors) => {
let quirks_mode = document_from_node(self).quirks_mode();
let root = DomRoot::from_ref(self);
// FIXME(bholley): Consider an nth-index cache here.
let mut ctx = MatchingContext::new(MatchingMode::Normal, None, None,
quirks_mode);
Ok(matches_selector_list(&selectors, &DomRoot::from_ref(self), &mut ctx))
ctx.scope_element = Some(root.opaque());
Ok(matches_selector_list(&selectors, &root, &mut ctx))
}
}
}
@ -2209,6 +2212,7 @@ impl ElementMethods for Element {
match SelectorParser::parse_author_origin_no_namespace(&selectors) {
Err(_) => Err(Error::Syntax),
Ok(selectors) => {
let self_root = DomRoot::from_ref(self);
let root = self.upcast::<Node>();
for element in root.inclusive_ancestors() {
if let Some(element) = DomRoot::downcast::<Element>(element) {
@ -2216,6 +2220,7 @@ impl ElementMethods for Element {
// FIXME(bholley): Consider an nth-index cache here.
let mut ctx = MatchingContext::new(MatchingMode::Normal, None, None,
quirks_mode);
ctx.scope_element = Some(self_root.opaque());
if matches_selector_list(&selectors, &element, &mut ctx) {
return Ok(Some(element));
}
@ -2500,7 +2505,7 @@ impl VirtualMethods for Element {
}
}
impl<'a> ::selectors::Element for DomRoot<Element> {
impl<'a> SelectorsElement for DomRoot<Element> {
type Impl = SelectorImpl;
fn opaque(&self) -> ::selectors::OpaqueElement {

View File

@ -284,7 +284,7 @@ fn complex_selector_specificity<Impl>(mut iter: slice::Iter<Component<Impl>>)
Component::FirstChild | Component::LastChild |
Component::OnlyChild | Component::Root |
Component::Empty |
Component::Empty | Component::Scope |
Component::NthChild(..) |
Component::NthLastChild(..) |
Component::NthOfType(..) |

View File

@ -5,6 +5,7 @@
use attr::CaseSensitivity;
use bloom::BloomFilter;
use nth_index_cache::NthIndexCache;
use tree::OpaqueElement;
/// What kind of selector matching mode we should use.
///
@ -88,6 +89,19 @@ pub struct MatchingContext<'a> {
/// only.)
pub relevant_link_found: bool,
/// The element which is going to match :scope pseudo-class. It can be
/// either one :scope element, or the scoping element.
///
/// Note that, although in theory there can be multiple :scope elements,
/// in current specs, at most one is specified, and when there is one,
/// scoping element is not relevant anymore, so we use a single field for
/// them.
///
/// When this is None, :scope will match the root element.
///
/// See https://drafts.csswg.org/selectors-4/#scope-pseudo
pub scope_element: Option<OpaqueElement>,
quirks_mode: QuirksMode,
classes_and_ids_case_sensitivity: CaseSensitivity,
}
@ -125,6 +139,7 @@ impl<'a> MatchingContext<'a> {
quirks_mode,
relevant_link_found: false,
classes_and_ids_case_sensitivity: quirks_mode.classes_and_ids_case_sensitivity(),
scope_element: None,
}
}

View File

@ -724,6 +724,12 @@ fn matches_simple_selector<E, F>(
flags_setter(element, HAS_EMPTY_SELECTOR);
element.is_empty()
}
Component::Scope => {
match context.shared.scope_element {
Some(ref scope_element) => element.opaque() == *scope_element,
None => element.is_root(),
}
}
Component::NthChild(a, b) => {
matches_generic_nth_child(element, context, a, b, false, false, flags_setter)
}

View File

@ -673,6 +673,7 @@ pub enum Component<Impl: SelectorImpl> {
FirstChild, LastChild, OnlyChild,
Root,
Empty,
Scope,
NthChild(i32, i32),
NthLastChild(i32, i32),
NthOfType(i32, i32),
@ -969,6 +970,7 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
OnlyChild => dest.write_str(":only-child"),
Root => dest.write_str(":root"),
Empty => dest.write_str(":empty"),
Scope => dest.write_str(":scope"),
FirstOfType => dest.write_str(":first-of-type"),
LastOfType => dest.write_str(":last-of-type"),
OnlyOfType => dest.write_str(":only-of-type"),
@ -1699,6 +1701,7 @@ fn parse_simple_pseudo_class<'i, P, E, Impl>(parser: &P, name: CowRcStr<'i>)
"only-child" => Ok(Component::OnlyChild),
"root" => Ok(Component::Root),
"empty" => Ok(Component::Empty),
"scope" => Ok(Component::Scope),
"first-of-type" => Ok(Component::FirstOfType),
"last-of-type" => Ok(Component::LastOfType),
"only-of-type" => Ok(Component::OnlyOfType),

View File

@ -1530,6 +1530,7 @@ pub unsafe extern "C" fn Servo_SelectorList_Matches(
None,
element.owner_document_quirks_mode(),
);
context.scope_element = Some(element.opaque());
selectors::matching::matches_selector_list(selectors, &element, &mut context)
}