mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #6468 - servo:update-selectors, r=Ms2ger
Update rust-selectors r? @Ms2ger https://github.com/servo/rust-selectors/pull/33 <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6468) <!-- Reviewable:end -->
This commit is contained in:
commit
c331db1623
12 changed files with 153 additions and 168 deletions
|
@ -17,6 +17,7 @@ use wrapper::{LayoutElement, LayoutNode};
|
||||||
use script::dom::characterdata::CharacterDataTypeId;
|
use script::dom::characterdata::CharacterDataTypeId;
|
||||||
use script::dom::node::NodeTypeId;
|
use script::dom::node::NodeTypeId;
|
||||||
use script::layout_interface::Animation;
|
use script::layout_interface::Animation;
|
||||||
|
use selectors::{Node, Element};
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
use selectors::matching::{CommonStyleAffectingAttributeMode, CommonStyleAffectingAttributes};
|
use selectors::matching::{CommonStyleAffectingAttributeMode, CommonStyleAffectingAttributes};
|
||||||
use selectors::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
|
use selectors::matching::{common_style_affecting_attributes, rare_style_affecting_attributes};
|
||||||
|
@ -28,7 +29,7 @@ use std::slice::Iter;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
use string_cache::{Atom, Namespace};
|
use string_cache::{Atom, Namespace};
|
||||||
use style::node::{TElement, TElementAttributes, TNode};
|
use style::node::TElementAttributes;
|
||||||
use style::properties::{ComputedValues, cascade};
|
use style::properties::{ComputedValues, cascade};
|
||||||
use style::selector_matching::{Stylist, DeclarationBlock};
|
use style::selector_matching::{Stylist, DeclarationBlock};
|
||||||
use util::arc_ptr_eq;
|
use util::arc_ptr_eq;
|
||||||
|
@ -226,9 +227,10 @@ impl StyleSharingCandidate {
|
||||||
None => return None,
|
None => return None,
|
||||||
Some(parent_node) => parent_node,
|
Some(parent_node) => parent_node,
|
||||||
};
|
};
|
||||||
if !parent_node.is_element() {
|
let element = match parent_node.as_element() {
|
||||||
return None
|
Some(element) => element,
|
||||||
}
|
None => return None
|
||||||
|
};
|
||||||
|
|
||||||
let style = unsafe {
|
let style = unsafe {
|
||||||
match *node.borrow_layout_data_unchecked() {
|
match *node.borrow_layout_data_unchecked() {
|
||||||
|
@ -253,7 +255,6 @@ impl StyleSharingCandidate {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let element = node.as_element();
|
|
||||||
if element.style_attribute().is_some() {
|
if element.style_attribute().is_some() {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
|
@ -504,10 +505,10 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
||||||
parent_node: Option<LayoutNode>,
|
parent_node: Option<LayoutNode>,
|
||||||
candidate: &StyleSharingCandidate)
|
candidate: &StyleSharingCandidate)
|
||||||
-> Option<Arc<ComputedValues>> {
|
-> Option<Arc<ComputedValues>> {
|
||||||
assert!(self.is_element());
|
let element = self.as_element().unwrap();
|
||||||
|
|
||||||
let parent_node = match parent_node {
|
let parent_node = match parent_node {
|
||||||
Some(ref parent_node) if parent_node.is_element() => parent_node,
|
Some(ref parent_node) if parent_node.as_element().is_some() => parent_node,
|
||||||
Some(_) | None => return None,
|
Some(_) | None => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -523,7 +524,7 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check tag names, classes, etc.
|
// Check tag names, classes, etc.
|
||||||
if !candidate.can_share_style_with(&self.as_element()) {
|
if !candidate.can_share_style_with(&element) {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,20 +543,21 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
parent_bf: &Option<Box<BloomFilter>>,
|
parent_bf: &Option<Box<BloomFilter>>,
|
||||||
applicable_declarations: &mut ApplicableDeclarations,
|
applicable_declarations: &mut ApplicableDeclarations,
|
||||||
shareable: &mut bool) {
|
shareable: &mut bool) {
|
||||||
let style_attribute = self.as_element().style_attribute().as_ref();
|
let element = self.as_element().unwrap();
|
||||||
|
let style_attribute = element.style_attribute().as_ref();
|
||||||
|
|
||||||
applicable_declarations.normal_shareable =
|
applicable_declarations.normal_shareable =
|
||||||
stylist.push_applicable_declarations(self,
|
stylist.push_applicable_declarations(&element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
style_attribute,
|
style_attribute,
|
||||||
None,
|
None,
|
||||||
&mut applicable_declarations.normal);
|
&mut applicable_declarations.normal);
|
||||||
stylist.push_applicable_declarations(self,
|
stylist.push_applicable_declarations(&element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
None,
|
None,
|
||||||
Some(PseudoElement::Before),
|
Some(PseudoElement::Before),
|
||||||
&mut applicable_declarations.before);
|
&mut applicable_declarations.before);
|
||||||
stylist.push_applicable_declarations(self,
|
stylist.push_applicable_declarations(&element,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
None,
|
None,
|
||||||
Some(PseudoElement::After),
|
Some(PseudoElement::After),
|
||||||
|
@ -574,13 +576,13 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
if opts::get().disable_share_style_cache {
|
if opts::get().disable_share_style_cache {
|
||||||
return StyleSharingResult::CannotShare(false)
|
return StyleSharingResult::CannotShare(false)
|
||||||
}
|
}
|
||||||
if !self.is_element() {
|
|
||||||
return StyleSharingResult::CannotShare(false)
|
|
||||||
}
|
|
||||||
let ok = {
|
let ok = {
|
||||||
let element = self.as_element();
|
if let Some(element) = self.as_element() {
|
||||||
element.style_attribute().is_none() &&
|
element.style_attribute().is_none() &&
|
||||||
element.get_attr(&ns!(""), &atom!("id")).is_none()
|
element.get_attr(&ns!(""), &atom!("id")).is_none()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if !ok {
|
if !ok {
|
||||||
return StyleSharingResult::CannotShare(false)
|
return StyleSharingResult::CannotShare(false)
|
||||||
|
@ -621,28 +623,26 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
|
|
||||||
fn insert_into_bloom_filter(&self, bf: &mut BloomFilter) {
|
fn insert_into_bloom_filter(&self, bf: &mut BloomFilter) {
|
||||||
// Only elements are interesting.
|
// Only elements are interesting.
|
||||||
if !self.is_element() { return; }
|
if let Some(element) = self.as_element() {
|
||||||
let element = self.as_element();
|
bf.insert(element.get_local_name());
|
||||||
|
bf.insert(element.get_namespace());
|
||||||
|
element.get_id().map(|id| bf.insert(&id));
|
||||||
|
|
||||||
bf.insert(element.get_local_name());
|
// TODO: case-sensitivity depends on the document type and quirks mode
|
||||||
bf.insert(element.get_namespace());
|
element.each_class(|class| bf.insert(class));
|
||||||
element.get_id().map(|id| bf.insert(&id));
|
}
|
||||||
|
|
||||||
// TODO: case-sensitivity depends on the document type and quirks mode
|
|
||||||
element.each_class(|class| bf.insert(class));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_from_bloom_filter(&self, bf: &mut BloomFilter) {
|
fn remove_from_bloom_filter(&self, bf: &mut BloomFilter) {
|
||||||
// Only elements are interesting.
|
// Only elements are interesting.
|
||||||
if !self.is_element() { return; }
|
if let Some(element) = self.as_element() {
|
||||||
let element = self.as_element();
|
bf.remove(element.get_local_name());
|
||||||
|
bf.remove(element.get_namespace());
|
||||||
|
element.get_id().map(|id| bf.remove(&id));
|
||||||
|
|
||||||
bf.remove(element.get_local_name());
|
// TODO: case-sensitivity depends on the document type and quirks mode
|
||||||
bf.remove(element.get_namespace());
|
element.each_class(|class| bf.remove(class));
|
||||||
element.get_id().map(|id| bf.remove(&id));
|
}
|
||||||
|
|
||||||
// TODO: case-sensitivity depends on the document type and quirks mode
|
|
||||||
element.each_class(|class| bf.remove(class));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn cascade_node(&self,
|
unsafe fn cascade_node(&self,
|
||||||
|
|
|
@ -41,7 +41,6 @@ use style::computed_values::content::ContentItem;
|
||||||
use style::computed_values::{border_collapse, clear, mix_blend_mode, overflow_wrap, position};
|
use style::computed_values::{border_collapse, clear, mix_blend_mode, overflow_wrap, position};
|
||||||
use style::computed_values::{text_align, text_decoration, white_space, word_break};
|
use style::computed_values::{text_align, text_decoration, white_space, word_break};
|
||||||
use style::computed_values::transform_style;
|
use style::computed_values::transform_style;
|
||||||
use style::node::TNode;
|
|
||||||
use style::properties::{self, ComputedValues, cascade_anonymous};
|
use style::properties::{self, ComputedValues, cascade_anonymous};
|
||||||
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
use style::values::computed::{LengthOrPercentageOrNone};
|
use style::values::computed::{LengthOrPercentageOrNone};
|
||||||
|
|
|
@ -19,9 +19,9 @@ use wrapper::{PostorderNodeMutTraversal, ThreadSafeLayoutNode, UnsafeLayoutNode}
|
||||||
use wrapper::{PreorderDomTraversal, PostorderDomTraversal};
|
use wrapper::{PreorderDomTraversal, PostorderDomTraversal};
|
||||||
|
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
|
use selectors::Node;
|
||||||
use util::opts;
|
use util::opts;
|
||||||
use util::tid::tid;
|
use util::tid::tid;
|
||||||
use style::node::TNode;
|
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -164,7 +164,7 @@ impl<'a> PreorderDomTraversal for RecalcStyleForNode<'a> {
|
||||||
StyleSharingResult::CannotShare(mut shareable) => {
|
StyleSharingResult::CannotShare(mut shareable) => {
|
||||||
let mut applicable_declarations = ApplicableDeclarations::new();
|
let mut applicable_declarations = ApplicableDeclarations::new();
|
||||||
|
|
||||||
if node.is_element() {
|
if node.as_element().is_some() {
|
||||||
// Perform the CSS selector matching.
|
// Perform the CSS selector matching.
|
||||||
let stylist = unsafe { &*self.layout_context.shared.stylist };
|
let stylist = unsafe { &*self.layout_context.shared.stylist };
|
||||||
node.match_node(stylist,
|
node.match_node(stylist,
|
||||||
|
|
|
@ -43,7 +43,7 @@ use script::dom::bindings::codegen::InheritTypes::{CharacterDataCast, ElementCas
|
||||||
use script::dom::bindings::codegen::InheritTypes::{HTMLIFrameElementCast, HTMLCanvasElementCast};
|
use script::dom::bindings::codegen::InheritTypes::{HTMLIFrameElementCast, HTMLCanvasElementCast};
|
||||||
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementCast, HTMLInputElementCast};
|
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementCast, HTMLInputElementCast};
|
||||||
use script::dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementCast, NodeCast, TextCast};
|
use script::dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementCast, NodeCast, TextCast};
|
||||||
use script::dom::bindings::js::LayoutJS;
|
use script::dom::bindings::js::{JS, LayoutJS};
|
||||||
use script::dom::characterdata::{CharacterDataTypeId, LayoutCharacterDataHelpers};
|
use script::dom::characterdata::{CharacterDataTypeId, LayoutCharacterDataHelpers};
|
||||||
use script::dom::element::{Element, ElementTypeId};
|
use script::dom::element::{Element, ElementTypeId};
|
||||||
use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers};
|
use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers};
|
||||||
|
@ -68,10 +68,11 @@ use std::sync::mpsc::Sender;
|
||||||
use string_cache::{Atom, Namespace};
|
use string_cache::{Atom, Namespace};
|
||||||
use style::computed_values::content::ContentItem;
|
use style::computed_values::content::ContentItem;
|
||||||
use style::computed_values::{content, display, white_space};
|
use style::computed_values::{content, display, white_space};
|
||||||
|
use selectors::Node as SelectorsNode;
|
||||||
use selectors::matching::DeclarationBlock;
|
use selectors::matching::DeclarationBlock;
|
||||||
use selectors::parser::{NamespaceConstraint, AttrSelector};
|
use selectors::parser::{NamespaceConstraint, AttrSelector};
|
||||||
use style::legacy::UnsignedIntegerAttribute;
|
use style::legacy::UnsignedIntegerAttribute;
|
||||||
use style::node::{TElement, TElementAttributes, TNode};
|
use style::node::TElementAttributes;
|
||||||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -216,9 +217,7 @@ impl<'ln> LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> TNode for LayoutNode<'ln> {
|
impl<'ln> ::selectors::Node<LayoutElement<'ln>> for LayoutNode<'ln> {
|
||||||
type Element = LayoutElement<'ln>;
|
|
||||||
|
|
||||||
fn parent_node(&self) -> Option<LayoutNode<'ln>> {
|
fn parent_node(&self) -> Option<LayoutNode<'ln>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node))
|
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node))
|
||||||
|
@ -249,25 +248,15 @@ impl<'ln> TNode for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If this is an element, accesses the element data. Fails if this is not an element node.
|
/// If this is an element, accesses the element data.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_element(&self) -> LayoutElement<'ln> {
|
fn as_element(&self) -> Option<LayoutElement<'ln>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let elem: LayoutJS<Element> = match ElementCast::to_layout_js(&self.node) {
|
ElementCast::to_layout_js(&self.node).map(|element| {
|
||||||
Some(elem) => elem,
|
LayoutElement {
|
||||||
None => panic!("not an element")
|
element: &*element.unsafe_get(),
|
||||||
};
|
}
|
||||||
|
})
|
||||||
LayoutElement {
|
|
||||||
element: &*elem.unsafe_get(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_element(&self) -> bool {
|
|
||||||
match self.type_id() {
|
|
||||||
NodeTypeId::Element(..) => true,
|
|
||||||
_ => false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,34 +266,6 @@ impl<'ln> TNode for LayoutNode<'ln> {
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool {
|
|
||||||
assert!(self.is_element());
|
|
||||||
let name = if self.is_html_element_in_html_document() {
|
|
||||||
&attr.lower_name
|
|
||||||
} else {
|
|
||||||
&attr.name
|
|
||||||
};
|
|
||||||
match attr.namespace {
|
|
||||||
NamespaceConstraint::Specific(ref ns) => {
|
|
||||||
let element = self.as_element();
|
|
||||||
element.get_attr(ns, name).map_or(false, |attr| test(attr))
|
|
||||||
},
|
|
||||||
NamespaceConstraint::Any => {
|
|
||||||
let element = self.as_element();
|
|
||||||
element.get_attrs(name).iter().any(|attr| test(*attr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_html_element_in_html_document(&self) -> bool {
|
|
||||||
unsafe {
|
|
||||||
match ElementCast::to_layout_js(&self.node) {
|
|
||||||
Some(elem) => elem.html_element_in_html_document_for_layout(),
|
|
||||||
None => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> LayoutNode<'ln> {
|
impl<'ln> LayoutNode<'ln> {
|
||||||
|
@ -424,7 +385,19 @@ impl<'le> LayoutElement<'le> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'le> TElement for LayoutElement<'le> {
|
impl<'le> ::selectors::Element for LayoutElement<'le> {
|
||||||
|
type Node = LayoutNode<'le>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_node(&self) -> LayoutNode<'le> {
|
||||||
|
LayoutNode {
|
||||||
|
node: NodeCast::from_layout_js(unsafe {
|
||||||
|
&JS::from_ref(self.element).to_layout()
|
||||||
|
}),
|
||||||
|
chain: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_local_name<'a>(&'a self) -> &'a Atom {
|
fn get_local_name<'a>(&'a self) -> &'a Atom {
|
||||||
self.element.local_name()
|
self.element.local_name()
|
||||||
|
@ -545,6 +518,28 @@ impl<'le> TElement for LayoutElement<'le> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool where F: Fn(&str) -> bool {
|
||||||
|
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, name).map_or(false, |attr| test(attr))
|
||||||
|
},
|
||||||
|
NamespaceConstraint::Any => {
|
||||||
|
self.get_attrs(name).iter().any(|attr| test(*attr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_html_element_in_html_document(&self) -> bool {
|
||||||
|
unsafe {
|
||||||
|
JS::from_ref(self.element).to_layout().html_element_in_html_document_for_layout()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'le> TElementAttributes for LayoutElement<'le> {
|
impl<'le> TElementAttributes for LayoutElement<'le> {
|
||||||
|
|
|
@ -79,6 +79,7 @@ use html5ever::serialize::TraversalScope::{IncludeNode, ChildrenOnly};
|
||||||
use html5ever::tree_builder::{NoQuirks, LimitedQuirks, Quirks};
|
use html5ever::tree_builder::{NoQuirks, LimitedQuirks, Quirks};
|
||||||
use selectors::matching::{matches, DeclarationBlock};
|
use selectors::matching::{matches, DeclarationBlock};
|
||||||
use selectors::parser::parse_author_origin_selector_list_from_str;
|
use selectors::parser::parse_author_origin_selector_list_from_str;
|
||||||
|
use selectors::parser::{AttrSelector, NamespaceConstraint};
|
||||||
use string_cache::{Atom, Namespace, QualName};
|
use string_cache::{Atom, Namespace, QualName};
|
||||||
use url::UrlParser;
|
use url::UrlParser;
|
||||||
|
|
||||||
|
@ -1454,8 +1455,7 @@ impl<'a> ElementMethods for &'a Element {
|
||||||
match parse_author_origin_selector_list_from_str(&selectors) {
|
match parse_author_origin_selector_list_from_str(&selectors) {
|
||||||
Err(()) => Err(Syntax),
|
Err(()) => Err(Syntax),
|
||||||
Ok(ref selectors) => {
|
Ok(ref selectors) => {
|
||||||
let root = NodeCast::from_ref(self);
|
Ok(matches(selectors, &self, &mut None))
|
||||||
Ok(matches(selectors, &root, &mut None))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1468,7 +1468,7 @@ impl<'a> ElementMethods for &'a Element {
|
||||||
let root = NodeCast::from_ref(self);
|
let root = NodeCast::from_ref(self);
|
||||||
for element in root.inclusive_ancestors() {
|
for element in root.inclusive_ancestors() {
|
||||||
if let Some(element) = ElementCast::to_ref(element.r()) {
|
if let Some(element) = ElementCast::to_ref(element.r()) {
|
||||||
if matches(selectors, &NodeCast::from_ref(element), &mut None) {
|
if matches(selectors, &element, &mut None) {
|
||||||
return Ok(Some(Root::from_ref(element)));
|
return Ok(Some(Root::from_ref(element)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1621,7 +1621,13 @@ impl<'a> VirtualMethods for &'a Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> style::node::TElement for &'a Element {
|
impl<'a> ::selectors::Element for &'a Element {
|
||||||
|
type Node = &'a Node;
|
||||||
|
|
||||||
|
fn as_node(&self) -> &'a Node {
|
||||||
|
NodeCast::from_ref(*self)
|
||||||
|
}
|
||||||
|
|
||||||
fn is_link(&self) -> bool {
|
fn is_link(&self) -> bool {
|
||||||
// FIXME: This is HTML only.
|
// FIXME: This is HTML only.
|
||||||
let node = NodeCast::from_ref(*self);
|
let node = NodeCast::from_ref(*self);
|
||||||
|
@ -1740,6 +1746,43 @@ impl<'a> style::node::TElement for &'a Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
|
||||||
|
where F: Fn(&str) -> bool
|
||||||
|
{
|
||||||
|
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, local_name)
|
||||||
|
.map_or(false, |attr| {
|
||||||
|
// FIXME(https://github.com/rust-lang/rust/issues/23338)
|
||||||
|
let attr = attr.r();
|
||||||
|
let value = attr.value();
|
||||||
|
test(&value)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
NamespaceConstraint::Any => {
|
||||||
|
let mut attributes: RootedVec<JS<Attr>> = RootedVec::new();
|
||||||
|
self.get_attributes(local_name, &mut attributes);
|
||||||
|
attributes.iter().any(|attr| {
|
||||||
|
// FIXME(https://github.com/rust-lang/rust/issues/23338)
|
||||||
|
let attr = attr.root();
|
||||||
|
let value = attr.r().value();
|
||||||
|
test(&value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_html_element_in_html_document(&self) -> bool {
|
||||||
|
self.html_element_in_html_document()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ActivationElementHelpers<'a> {
|
pub trait ActivationElementHelpers<'a> {
|
||||||
|
|
|
@ -54,7 +54,7 @@ use util::geometry::Au;
|
||||||
use util::namespace;
|
use util::namespace;
|
||||||
use util::str::DOMString;
|
use util::str::DOMString;
|
||||||
use util::task_state;
|
use util::task_state;
|
||||||
use selectors::parser::{Selector, AttrSelector, NamespaceConstraint};
|
use selectors::parser::Selector;
|
||||||
use selectors::parser::parse_author_origin_selector_list_from_str;
|
use selectors::parser::parse_author_origin_selector_list_from_str;
|
||||||
use selectors::matching::matches;
|
use selectors::matching::matches;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
@ -423,7 +423,11 @@ impl<'a> Iterator for QuerySelectorIterator {
|
||||||
// TODO(cgaebel): Is it worth it to build a bloom filter here
|
// TODO(cgaebel): Is it worth it to build a bloom filter here
|
||||||
// (instead of passing `None`)? Probably.
|
// (instead of passing `None`)? Probably.
|
||||||
self.iterator.find(|node| {
|
self.iterator.find(|node| {
|
||||||
node.r().is_element() && matches(selectors, &node.r(), &mut None)
|
if let Some(element) = ElementCast::to_ref(node.r()) {
|
||||||
|
matches(selectors, &element, &mut None)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -896,7 +900,7 @@ impl<'a> NodeHelpers for &'a Node {
|
||||||
let root = self.ancestors().last();
|
let root = self.ancestors().last();
|
||||||
let root = root.r().unwrap_or(self.clone());
|
let root = root.r().unwrap_or(self.clone());
|
||||||
Ok(root.traverse_preorder().filter_map(ElementCast::to_root).find(|element| {
|
Ok(root.traverse_preorder().filter_map(ElementCast::to_root).find(|element| {
|
||||||
matches(selectors, &NodeCast::from_ref(element.r()), &mut None)
|
matches(selectors, &element.r(), &mut None)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2506,9 +2510,7 @@ impl<'a> VirtualMethods for &'a Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> style::node::TNode for &'a Node {
|
impl<'a> ::selectors::Node<&'a Element> for &'a Node {
|
||||||
type Element = &'a Element;
|
|
||||||
|
|
||||||
fn parent_node(&self) -> Option<&'a Node> {
|
fn parent_node(&self) -> Option<&'a Node> {
|
||||||
(*self).parent_node.get()
|
(*self).parent_node.get()
|
||||||
.map(|node| node.root().get_unsound_ref_forever())
|
.map(|node| node.root().get_unsound_ref_forever())
|
||||||
|
@ -2544,55 +2546,8 @@ impl<'a> style::node::TNode for &'a Node {
|
||||||
is_document(*self)
|
is_document(*self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_element(&self) -> bool {
|
fn as_element(&self) -> Option<&'a Element> {
|
||||||
// FIXME(zwarich): Remove this when UFCS lands and there is a better way
|
ElementCast::to_ref(*self)
|
||||||
// of disambiguating methods.
|
|
||||||
fn is_element<'a, T: ElementDerived>(this: &T) -> bool {
|
|
||||||
this.is_element()
|
|
||||||
}
|
|
||||||
|
|
||||||
is_element(*self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_element(&self) -> &'a Element {
|
|
||||||
ElementCast::to_ref(*self).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn match_attr<F>(&self, attr: &AttrSelector, test: F) -> bool
|
|
||||||
where F: Fn(&str) -> bool
|
|
||||||
{
|
|
||||||
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.as_element().get_attribute(ns, local_name)
|
|
||||||
.map_or(false, |attr| {
|
|
||||||
// FIXME(https://github.com/rust-lang/rust/issues/23338)
|
|
||||||
let attr = attr.r();
|
|
||||||
let value = attr.value();
|
|
||||||
test(&value)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
NamespaceConstraint::Any => {
|
|
||||||
let mut attributes: RootedVec<JS<Attr>> = RootedVec::new();
|
|
||||||
self.as_element().get_attributes(local_name, &mut attributes);
|
|
||||||
attributes.iter().any(|attr| {
|
|
||||||
// FIXME(https://github.com/rust-lang/rust/issues/23338)
|
|
||||||
let attr = attr.root();
|
|
||||||
let value = attr.r().value();
|
|
||||||
test(&value)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_html_element_in_html_document(&self) -> bool {
|
|
||||||
self.as_element().html_element_in_html_document()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
components/servo/Cargo.lock
generated
2
components/servo/Cargo.lock
generated
|
@ -1116,7 +1116,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "selectors"
|
name = "selectors"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/rust-selectors#9c920bfff7e55dd67e8af45943270bcd71fd46c9"
|
source = "git+https://github.com/servo/rust-selectors#a16e32540845548d46857f2896248c382ef34393"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use selectors::tree::TNode;
|
use selectors::Element;
|
||||||
use selectors::matching::DeclarationBlock;
|
use selectors::matching::DeclarationBlock;
|
||||||
use node::TElementAttributes;
|
use node::TElementAttributes;
|
||||||
use properties::PropertyDeclaration;
|
use properties::PropertyDeclaration;
|
||||||
|
@ -32,21 +32,17 @@ pub trait PresentationalHintSynthesis {
|
||||||
/// `common_style_affecting_attributes` or `rare_style_affecting_attributes` as appropriate. If
|
/// `common_style_affecting_attributes` or `rare_style_affecting_attributes` as appropriate. If
|
||||||
/// you don't, you risk strange random nondeterministic failures due to false positives in
|
/// you don't, you risk strange random nondeterministic failures due to false positives in
|
||||||
/// style sharing.
|
/// style sharing.
|
||||||
fn synthesize_presentational_hints_for_legacy_attributes<N,V>(
|
fn synthesize_presentational_hints_for_legacy_attributes<E,V>(
|
||||||
&self, node: &N, matching_rules_list: &mut V, shareable: &mut bool)
|
&self, element: &E, matching_rules_list: &mut V, shareable: &mut bool)
|
||||||
where N: TNode,
|
where E: Element + TElementAttributes,
|
||||||
N::Element: TElementAttributes,
|
|
||||||
V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>;
|
V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PresentationalHintSynthesis for Stylist {
|
impl PresentationalHintSynthesis for Stylist {
|
||||||
fn synthesize_presentational_hints_for_legacy_attributes<N,V>(
|
fn synthesize_presentational_hints_for_legacy_attributes<E,V>(
|
||||||
&self, node: &N, matching_rules_list: &mut V, shareable: &mut bool)
|
&self, element: &E, matching_rules_list: &mut V, shareable: &mut bool)
|
||||||
where N: TNode,
|
where E: Element + TElementAttributes,
|
||||||
N::Element: TElementAttributes,
|
|
||||||
V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>> {
|
V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>> {
|
||||||
let element = node.as_element();
|
|
||||||
|
|
||||||
let length = matching_rules_list.len();
|
let length = matching_rules_list.len();
|
||||||
element.synthesize_presentational_hints_for_legacy_attributes(matching_rules_list);
|
element.synthesize_presentational_hints_for_legacy_attributes(matching_rules_list);
|
||||||
if matching_rules_list.len() != length {
|
if matching_rules_list.len() != length {
|
||||||
|
|
|
@ -10,7 +10,6 @@ use properties::PropertyDeclaration;
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
|
|
||||||
use selectors::matching::DeclarationBlock;
|
use selectors::matching::DeclarationBlock;
|
||||||
pub use selectors::tree::{TNode, TElement};
|
|
||||||
use string_cache::{Atom, Namespace};
|
use string_cache::{Atom, Namespace};
|
||||||
|
|
||||||
pub trait TElementAttributes {
|
pub trait TElementAttributes {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use selectors::bloom::BloomFilter;
|
||||||
use selectors::matching::{SelectorMap, Rule};
|
use selectors::matching::{SelectorMap, Rule};
|
||||||
use selectors::matching::DeclarationBlock as GenericDeclarationBlock;
|
use selectors::matching::DeclarationBlock as GenericDeclarationBlock;
|
||||||
use selectors::parser::PseudoElement;
|
use selectors::parser::PseudoElement;
|
||||||
use selectors::tree::TNode;
|
use selectors::Element;
|
||||||
use std::process;
|
use std::process;
|
||||||
use smallvec::VecLike;
|
use smallvec::VecLike;
|
||||||
use util::resource_files::read_resource_file;
|
use util::resource_files::read_resource_file;
|
||||||
|
@ -190,19 +190,17 @@ impl Stylist {
|
||||||
/// The returned boolean indicates whether the style is *shareable*; that is, whether the
|
/// The returned boolean indicates whether the style is *shareable*; that is, whether the
|
||||||
/// matched selectors are simple enough to allow the matching logic to be reduced to the logic
|
/// matched selectors are simple enough to allow the matching logic to be reduced to the logic
|
||||||
/// in `css::matching::PrivateMatchMethods::candidate_element_allows_for_style_sharing`.
|
/// in `css::matching::PrivateMatchMethods::candidate_element_allows_for_style_sharing`.
|
||||||
pub fn push_applicable_declarations<N,V>(
|
pub fn push_applicable_declarations<E,V>(
|
||||||
&self,
|
&self,
|
||||||
element: &N,
|
element: &E,
|
||||||
parent_bf: &Option<Box<BloomFilter>>,
|
parent_bf: &Option<Box<BloomFilter>>,
|
||||||
style_attribute: Option<&PropertyDeclarationBlock>,
|
style_attribute: Option<&PropertyDeclarationBlock>,
|
||||||
pseudo_element: Option<PseudoElement>,
|
pseudo_element: Option<PseudoElement>,
|
||||||
applicable_declarations: &mut V)
|
applicable_declarations: &mut V)
|
||||||
-> bool
|
-> bool
|
||||||
where N: TNode,
|
where E: Element + TElementAttributes,
|
||||||
N::Element: TElementAttributes,
|
|
||||||
V: VecLike<DeclarationBlock> {
|
V: VecLike<DeclarationBlock> {
|
||||||
assert!(!self.is_dirty);
|
assert!(!self.is_dirty);
|
||||||
assert!(element.is_element());
|
|
||||||
assert!(style_attribute.is_none() || pseudo_element.is_none(),
|
assert!(style_attribute.is_none() || pseudo_element.is_none(),
|
||||||
"Style attributes do not apply to pseudo-elements");
|
"Style attributes do not apply to pseudo-elements");
|
||||||
|
|
||||||
|
|
2
ports/cef/Cargo.lock
generated
2
ports/cef/Cargo.lock
generated
|
@ -1088,7 +1088,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "selectors"
|
name = "selectors"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/rust-selectors#9c920bfff7e55dd67e8af45943270bcd71fd46c9"
|
source = "git+https://github.com/servo/rust-selectors#a16e32540845548d46857f2896248c382ef34393"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
2
ports/gonk/Cargo.lock
generated
2
ports/gonk/Cargo.lock
generated
|
@ -996,7 +996,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "selectors"
|
name = "selectors"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/rust-selectors#9c920bfff7e55dd67e8af45943270bcd71fd46c9"
|
source = "git+https://github.com/servo/rust-selectors#a16e32540845548d46857f2896248c382ef34393"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue