Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shrink selectors::Component, implement attr selector (in)case-sensitivity #16915

Merged
merged 12 commits into from May 19, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Some generated files are not rendered by default. Learn more.

@@ -86,9 +86,9 @@ use net_traits::request::CorsSettings;
use ref_filter_map::ref_filter_map;
use script_layout_interface::message::ReflowQueryType;
use script_thread::Runnable;
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint};
use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode, matches_selector_list};
use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS};
use selectors::parser::{AttrSelector, NamespaceConstraint};
use servo_atoms::Atom;
use std::ascii::AsciiExt;
use std::borrow::Cow;
@@ -288,7 +288,7 @@ pub trait RawLayoutElementHelpers {
-> Option<&'a AttrValue>;
unsafe fn get_attr_val_for_layout<'a>(&'a self, namespace: &Namespace, name: &LocalName)
-> Option<&'a str>;
unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &LocalName) -> Vec<&'a str>;
unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &LocalName) -> Vec<&'a AttrValue>;
}

#[inline]
@@ -314,6 +314,7 @@ impl RawLayoutElementHelpers for Element {
})
}

#[inline]
unsafe fn get_attr_val_for_layout<'a>(&'a self, namespace: &Namespace, name: &LocalName)
-> Option<&'a str> {
get_attr_for_layout(self, namespace, name).map(|attr| {
@@ -322,12 +323,12 @@ impl RawLayoutElementHelpers for Element {
}

#[inline]
unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &LocalName) -> Vec<&'a str> {
unsafe fn get_attr_vals_for_layout<'a>(&'a self, name: &LocalName) -> Vec<&'a AttrValue> {
let attrs = self.attrs.borrow_for_layout();
attrs.iter().filter_map(|attr| {
let attr = attr.to_layout();
if *name == attr.local_name_atom_forever() {
Some(attr.value_ref_forever())
Some(attr.value_forever())
} else {
None
}
@@ -2352,37 +2353,9 @@ impl VirtualMethods for Element {
}
}

impl<'a> ::selectors::MatchAttrGeneric for Root<Element> {
impl<'a> ::selectors::Element for Root<Element> {
type Impl = SelectorImpl;

fn match_attr<F>(&self, attr: &AttrSelector<SelectorImpl>, test: F) -> bool
where F: Fn(&str) -> bool
{
use ::selectors::Element;
let local_name = {
if self.is_html_element_in_html_document() {
&attr.lower_name
} else {
&attr.name
}
};
match attr.namespace {
NamespaceConstraint::Specific(ref ns) => {
self.get_attribute(&ns.url, local_name)
.map_or(false, |attr| {
test(&attr.value())
})
},
NamespaceConstraint::Any => {
self.attrs.borrow().iter().any(|attr| {
attr.local_name() == local_name && test(&attr.value())
})
}
}
}
}

impl<'a> ::selectors::Element for Root<Element> {
fn parent_element(&self) -> Option<Root<Element>> {
self.upcast::<Node>().GetParentElement()
}
@@ -2412,6 +2385,25 @@ impl<'a> ::selectors::Element for Root<Element> {
self.node.following_siblings().filter_map(Root::downcast).next()
}

fn attr_matches(&self,
ns: &NamespaceConstraint<&Namespace>,
local_name: &LocalName,
operation: &AttrSelectorOperation<&String>)
-> bool {
match *ns {
NamespaceConstraint::Specific(ref ns) => {
self.get_attribute(ns, local_name)
.map_or(false, |attr| attr.value().eval_selector(operation))
}
NamespaceConstraint::Any => {
self.attrs.borrow().iter().any(|attr| {
attr.local_name() == local_name &&
attr.value().eval_selector(operation)
})
}
}
}

fn is_root(&self) -> bool {
match self.node.GetParentNode() {
None => false,
@@ -2459,6 +2451,11 @@ impl<'a> ::selectors::Element for Root<Element> {
}
},

NonTSPseudoClass::ServoCaseSensitiveTypeAttr(ref expected_value) => {
self.get_attribute(&ns!(), &local_name!("type"))
.map_or(false, |attr| attr.value().eq(expected_value))
}

// FIXME(#15746): This is wrong, we need to instead use extended filtering as per RFC4647
// https://tools.ietf.org/html/rfc4647#section-3.3.2
NonTSPseudoClass::Lang(ref lang) => extended_filtering(&*self.get_lang(), &*lang),
@@ -2489,18 +2486,6 @@ impl<'a> ::selectors::Element for Root<Element> {
Element::has_class(&**self, name)
}

fn each_class<F>(&self, mut callback: F)
where F: FnMut(&Atom)
{
if let Some(ref attr) = self.get_attribute(&ns!(), &local_name!("class")) {
let tokens = attr.value();
let tokens = tokens.as_tokens();
for token in tokens {
callback(token);
}
}
}

fn is_html_element_in_html_document(&self) -> bool {
self.html_element_in_html_document()
}
@@ -50,8 +50,8 @@ use script_layout_interface::{HTMLCanvasData, LayoutNodeType, SVGSVGData, Truste
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialPersistentLayoutData};
use script_layout_interface::wrapper_traits::{DangerousThreadSafeLayoutNode, GetLayoutData, LayoutNode};
use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use selectors::attr::{AttrSelectorOperation, NamespaceConstraint};
use selectors::matching::{ElementSelectorFlags, MatchingContext};
use selectors::parser::{AttrSelector, NamespaceConstraint};
use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::fmt;
@@ -402,6 +402,17 @@ impl<'le> TElement for ServoLayoutElement<'le> {
self.get_attr(namespace, attr).map_or(false, |x| x == val)
}

#[inline(always)]
fn each_class<F>(&self, mut callback: F) where F: FnMut(&Atom) {
unsafe {
if let Some(ref classes) = self.element.get_classes_for_layout() {
for class in *classes {
callback(class)
}
}
}
}

#[inline]
fn existing_style_for_restyle_damage<'a>(&'a self,
current_cv: &'a ComputedValues,
@@ -509,6 +520,13 @@ impl<'le> ServoLayoutElement<'le> {
}
}

#[inline]
fn get_attr_enum(&self, namespace: &Namespace, name: &LocalName) -> Option<&AttrValue> {
unsafe {
(*self.element.unsafe_get()).get_attr_for_layout(namespace, name)
}
}

#[inline]
fn get_attr(&self, namespace: &Namespace, name: &LocalName) -> Option<&str> {
unsafe {
@@ -558,32 +576,9 @@ fn as_element<'le>(node: LayoutJS<Node>) -> Option<ServoLayoutElement<'le>> {
node.downcast().map(ServoLayoutElement::from_layout_js)
}

impl<'le> ::selectors::MatchAttrGeneric for ServoLayoutElement<'le> {
impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
type Impl = SelectorImpl;

fn match_attr<F>(&self, attr: &AttrSelector<SelectorImpl>, test: F) -> bool
where F: Fn(&str) -> bool {
use ::selectors::Element;
let name = if self.is_html_element_in_html_document() {
&attr.lower_name
} else {
&attr.name
};
match attr.namespace {
NamespaceConstraint::Specific(ref ns) => {
self.get_attr(&ns.url, name).map_or(false, |attr| test(attr))
},
NamespaceConstraint::Any => {
let attrs = unsafe {
(*self.element.unsafe_get()).get_attr_vals_for_layout(name)
};
attrs.iter().any(|attr| test(*attr))
}
}
}
}

impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
fn parent_element(&self) -> Option<ServoLayoutElement<'le>> {
unsafe {
self.element.upcast().parent_node_ref().and_then(as_element)
@@ -620,6 +615,25 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
None
}

fn attr_matches(&self,
ns: &NamespaceConstraint<&Namespace>,
local_name: &LocalName,
operation: &AttrSelectorOperation<&String>)
-> bool {
match *ns {
NamespaceConstraint::Specific(ref ns) => {
self.get_attr_enum(ns, local_name)
.map_or(false, |value| value.eval_selector(operation))
}
NamespaceConstraint::Any => {
let values = unsafe {
(*self.element.unsafe_get()).get_attr_vals_for_layout(local_name)
};
values.iter().any(|value| value.eval_selector(operation))
}
}
}

fn is_root(&self) -> bool {
match self.as_node().parent_node() {
None => false,
@@ -692,7 +706,10 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
_ => true,
}
},

NonTSPseudoClass::ServoCaseSensitiveTypeAttr(ref expected_value) => {
self.get_attr_enum(&ns!(), &local_name!("type"))
.map_or(false, |attr| attr == expected_value)
}
NonTSPseudoClass::ReadOnly =>
!self.element.get_state_for_layout().contains(pseudo_class.state_flag()),

@@ -725,17 +742,6 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
}
}

#[inline(always)]
fn each_class<F>(&self, mut callback: F) where F: FnMut(&Atom) {
unsafe {
if let Some(ref classes) = self.element.get_classes_for_layout() {
for class in *classes {
callback(class)
}
}
}
}

fn is_html_element_in_html_document(&self) -> bool {
unsafe {
self.element.html_element_in_html_document_for_layout()
@@ -1075,6 +1081,10 @@ impl<'le> ThreadSafeLayoutElement for ServoThreadSafeLayoutElement<'le> {
self.element
}

fn get_attr_enum(&self, namespace: &Namespace, name: &LocalName) -> Option<&AttrValue> {
self.element.get_attr_enum(namespace, name)
}

fn get_attr<'a>(&'a self, namespace: &Namespace, name: &LocalName) -> Option<&'a str> {
self.element.get_attr(namespace, name)
}
@@ -1091,30 +1101,14 @@ impl<'le> ThreadSafeLayoutElement for ServoThreadSafeLayoutElement<'le> {
/// i.e., local_name, attributes, so they can only be used for **private**
/// pseudo-elements (like `::-servo-details-content`).
///
/// Probably a few more of this functions can be implemented (like `has_class`,
/// `each_class`, etc), but they have no use right now.
/// Probably a few more of this functions can be implemented (like `has_class`, etc.),
/// but they have no use right now.
///
/// Note that the element implementation is needed only for selector matching,
/// not for inheritance (styles are inherited appropiately).
impl<'le> ::selectors::MatchAttrGeneric for ServoThreadSafeLayoutElement<'le> {
impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
type Impl = SelectorImpl;

fn match_attr<F>(&self, attr: &AttrSelector<SelectorImpl>, test: F) -> bool
where F: Fn(&str) -> bool {
match attr.namespace {
NamespaceConstraint::Specific(ref ns) => {
self.get_attr(&ns.url, &attr.name).map_or(false, |attr| test(attr))
},
NamespaceConstraint::Any => {
unsafe {
(*self.element.element.unsafe_get()).get_attr_vals_for_layout(&attr.name).iter()
.any(|attr| test(*attr))
}
}
}
}
}
impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
fn parent_element(&self) -> Option<Self> {
warn!("ServoThreadSafeLayoutElement::parent_element called");
None
@@ -1166,6 +1160,25 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
false
}

fn attr_matches(&self,
ns: &NamespaceConstraint<&Namespace>,
local_name: &LocalName,
operation: &AttrSelectorOperation<&String>)
-> bool {
match *ns {
NamespaceConstraint::Specific(ref ns) => {
self.get_attr_enum(ns, local_name)
.map_or(false, |value| value.eval_selector(operation))
}
NamespaceConstraint::Any => {
let values = unsafe {
(*self.element.element.unsafe_get()).get_attr_vals_for_layout(local_name)
};
values.iter().any(|v| v.eval_selector(operation))
}
}
}

fn match_non_ts_pseudo_class<F>(&self,
_: &NonTSPseudoClass,
_: &mut MatchingContext,
@@ -1197,11 +1210,6 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
warn!("ServoThreadSafeLayoutElement::is_root called");
false
}

fn each_class<F>(&self, _callback: F)
where F: FnMut(&Atom) {
warn!("ServoThreadSafeLayoutElement::each_class called");
}
}

impl<'le> PresentationalHintsSynthesizer for ServoThreadSafeLayoutElement<'le> {
@@ -15,6 +15,7 @@ use msg::constellation_msg::{BrowsingContextId, PipelineId};
use range::Range;
use servo_url::ServoUrl;
use std::fmt::Debug;
use style::attr::AttrValue;
use style::computed_values::display;
use style::context::SharedStyleContext;
use style::data::ElementData;
@@ -335,6 +336,8 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
#[inline]
fn get_attr(&self, namespace: &Namespace, name: &LocalName) -> Option<&str>;

fn get_attr_enum(&self, namespace: &Namespace, name: &LocalName) -> Option<&AttrValue>;

fn get_style_data(&self) -> Option<&AtomicRefCell<ElementData>>;

#[inline]
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.