mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Auto merge of #18988 - emilio:qs, r=heycam
stylo: querySelector / querySelectorAll machinery. Bug: 1410624 Reviewed-by: heycam <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18988) <!-- Reviewable:end -->
This commit is contained in:
commit
eaba7ede23
13 changed files with 1555 additions and 1168 deletions
|
@ -338,8 +338,7 @@ pub fn matches_compound_selector<E>(
|
||||||
where
|
where
|
||||||
E: Element
|
E: Element
|
||||||
{
|
{
|
||||||
debug_assert_ne!(from_offset, 0);
|
if cfg!(debug_assertions) && from_offset != 0 {
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
selector.combinator_at_parse_order(from_offset - 1); // This asserts.
|
selector.combinator_at_parse_order(from_offset - 1); // This asserts.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage};
|
||||||
use selectors::NthIndexCache;
|
use selectors::NthIndexCache;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use shared_lock::StylesheetGuards;
|
use shared_lock::StylesheetGuards;
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
@ -259,17 +260,22 @@ impl ElementData {
|
||||||
return InvalidationResult::empty();
|
return InvalidationResult::empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut xbl_stylists = SmallVec::<[_; 3]>::new();
|
||||||
|
let cut_off_inheritance =
|
||||||
|
element.each_xbl_stylist(|s| xbl_stylists.push(s));
|
||||||
|
|
||||||
let mut processor = StateAndAttrInvalidationProcessor::new(
|
let mut processor = StateAndAttrInvalidationProcessor::new(
|
||||||
shared_context,
|
shared_context,
|
||||||
|
&xbl_stylists,
|
||||||
|
cut_off_inheritance,
|
||||||
element,
|
element,
|
||||||
self,
|
self,
|
||||||
|
nth_index_cache,
|
||||||
);
|
);
|
||||||
|
|
||||||
let invalidator = TreeStyleInvalidator::new(
|
let invalidator = TreeStyleInvalidator::new(
|
||||||
element,
|
element,
|
||||||
shared_context.quirks_mode(),
|
|
||||||
stack_limit_checker,
|
stack_limit_checker,
|
||||||
nth_index_cache,
|
|
||||||
&mut processor,
|
&mut processor,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -110,9 +110,32 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An iterator over the DOM descendants of a node in pre-order.
|
||||||
|
pub struct DomDescendants<N> {
|
||||||
|
previous: Option<N>,
|
||||||
|
scope: N,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N> Iterator for DomDescendants<N>
|
||||||
|
where
|
||||||
|
N: TNode
|
||||||
|
{
|
||||||
|
type Item = N;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<N> {
|
||||||
|
let prev = match self.previous.take() {
|
||||||
|
None => return None,
|
||||||
|
Some(n) => n,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.previous = prev.next_in_preorder(Some(self.scope));
|
||||||
|
self.previous
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The `TNode` trait. This is the main generic trait over which the style
|
/// The `TNode` trait. This is the main generic trait over which the style
|
||||||
/// system can be implemented.
|
/// system can be implemented.
|
||||||
pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo {
|
pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo + PartialEq {
|
||||||
/// The concrete `TElement` type.
|
/// The concrete `TElement` type.
|
||||||
type ConcreteElement: TElement<ConcreteNode = Self>;
|
type ConcreteElement: TElement<ConcreteNode = Self>;
|
||||||
|
|
||||||
|
@ -131,11 +154,45 @@ pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo {
|
||||||
/// Get this node's next sibling.
|
/// Get this node's next sibling.
|
||||||
fn next_sibling(&self) -> Option<Self>;
|
fn next_sibling(&self) -> Option<Self>;
|
||||||
|
|
||||||
/// Iterate over the DOM children of an element.
|
/// Iterate over the DOM children of a node.
|
||||||
fn dom_children(&self) -> DomChildren<Self> {
|
fn dom_children(&self) -> DomChildren<Self> {
|
||||||
DomChildren(self.first_child())
|
DomChildren(self.first_child())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterate over the DOM children of a node, in preorder.
|
||||||
|
fn dom_descendants(&self) -> DomDescendants<Self> {
|
||||||
|
DomDescendants {
|
||||||
|
previous: Some(*self),
|
||||||
|
scope: *self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the next children in pre-order, optionally scoped to a subtree
|
||||||
|
/// root.
|
||||||
|
fn next_in_preorder(&self, scoped_to: Option<Self>) -> Option<Self> {
|
||||||
|
if let Some(c) = self.first_child() {
|
||||||
|
return Some(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if Some(*self) == scoped_to {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut current = *self;
|
||||||
|
loop {
|
||||||
|
if let Some(s) = current.next_sibling() {
|
||||||
|
return Some(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent = current.parent_node();
|
||||||
|
if parent == scoped_to {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = parent.expect("Not a descendant of the scope?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get this node's parent element from the perspective of a restyle
|
/// Get this node's parent element from the perspective of a restyle
|
||||||
/// traversal.
|
/// traversal.
|
||||||
fn traversal_parent(&self) -> Option<Self::ConcreteElement>;
|
fn traversal_parent(&self) -> Option<Self::ConcreteElement>;
|
||||||
|
@ -686,9 +743,10 @@ pub trait TElement
|
||||||
/// Implements Gecko's `nsBindingManager::WalkRules`.
|
/// Implements Gecko's `nsBindingManager::WalkRules`.
|
||||||
///
|
///
|
||||||
/// Returns whether to cut off the inheritance.
|
/// Returns whether to cut off the inheritance.
|
||||||
fn each_xbl_stylist<F>(&self, _: F) -> bool
|
fn each_xbl_stylist<'a, F>(&self, _: F) -> bool
|
||||||
where
|
where
|
||||||
F: FnMut(&Stylist),
|
Self: 'a,
|
||||||
|
F: FnMut(AtomicRef<'a, Stylist>),
|
||||||
{
|
{
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,11 @@
|
||||||
//! and Gecko.
|
//! and Gecko.
|
||||||
|
|
||||||
use context::QuirksMode;
|
use context::QuirksMode;
|
||||||
|
use dom::{TElement, TNode};
|
||||||
|
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
|
||||||
use selectors::{Element, NthIndexCache, SelectorList};
|
use selectors::{Element, NthIndexCache, SelectorList};
|
||||||
use selectors::matching::{self, MatchingContext, MatchingMode};
|
use selectors::matching::{self, MatchingContext, MatchingMode};
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
/// <https://dom.spec.whatwg.org/#dom-element-matches>
|
/// <https://dom.spec.whatwg.org/#dom-element-matches>
|
||||||
pub fn element_matches<E>(
|
pub fn element_matches<E>(
|
||||||
|
@ -57,3 +60,317 @@ where
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A selector query abstraction, in order to be generic over QuerySelector and
|
||||||
|
/// QuerySelectorAll.
|
||||||
|
pub trait SelectorQuery<E: TElement> {
|
||||||
|
/// The output of the query.
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
/// Whether the query should stop after the first element has been matched.
|
||||||
|
fn should_stop_after_first_match() -> bool;
|
||||||
|
|
||||||
|
/// Append an element matching after the first query.
|
||||||
|
fn append_element(output: &mut Self::Output, element: E);
|
||||||
|
|
||||||
|
/// Returns true if the output is empty.
|
||||||
|
fn is_empty(output: &Self::Output) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The result of a querySelectorAll call.
|
||||||
|
pub type QuerySelectorAllResult<E> = SmallVec<[E; 128]>;
|
||||||
|
|
||||||
|
/// A query for all the elements in a subtree.
|
||||||
|
pub struct QueryAll;
|
||||||
|
|
||||||
|
impl<E: TElement> SelectorQuery<E> for QueryAll {
|
||||||
|
type Output = QuerySelectorAllResult<E>;
|
||||||
|
|
||||||
|
fn should_stop_after_first_match() -> bool { false }
|
||||||
|
|
||||||
|
fn append_element(output: &mut Self::Output, element: E) {
|
||||||
|
output.push(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_empty(output: &Self::Output) -> bool {
|
||||||
|
output.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A query for the first in-tree match of all the elements in a subtree.
|
||||||
|
pub struct QueryFirst;
|
||||||
|
|
||||||
|
impl<E: TElement> SelectorQuery<E> for QueryFirst {
|
||||||
|
type Output = Option<E>;
|
||||||
|
|
||||||
|
fn should_stop_after_first_match() -> bool { true }
|
||||||
|
|
||||||
|
fn append_element(output: &mut Self::Output, element: E) {
|
||||||
|
if output.is_none() {
|
||||||
|
*output = Some(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_empty(output: &Self::Output) -> bool {
|
||||||
|
output.is_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct QuerySelectorProcessor<'a, E, Q>
|
||||||
|
where
|
||||||
|
E: TElement + 'a,
|
||||||
|
Q: SelectorQuery<E>,
|
||||||
|
Q::Output: 'a,
|
||||||
|
{
|
||||||
|
results: &'a mut Q::Output,
|
||||||
|
matching_context: MatchingContext<'a, E::Impl>,
|
||||||
|
selector_list: &'a SelectorList<E::Impl>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, E, Q> InvalidationProcessor<'a, E> for QuerySelectorProcessor<'a, E, Q>
|
||||||
|
where
|
||||||
|
E: TElement + 'a,
|
||||||
|
Q: SelectorQuery<E>,
|
||||||
|
Q::Output: 'a,
|
||||||
|
{
|
||||||
|
fn light_tree_only(&self) -> bool { true }
|
||||||
|
|
||||||
|
fn collect_invalidations(
|
||||||
|
&mut self,
|
||||||
|
element: E,
|
||||||
|
self_invalidations: &mut InvalidationVector<'a>,
|
||||||
|
descendant_invalidations: &mut InvalidationVector<'a>,
|
||||||
|
_sibling_invalidations: &mut InvalidationVector<'a>,
|
||||||
|
) -> bool {
|
||||||
|
// TODO(emilio): If the element is not a root element, and
|
||||||
|
// selector_list has any descendant combinator, we need to do extra work
|
||||||
|
// in order to handle properly things like:
|
||||||
|
//
|
||||||
|
// <div id="a">
|
||||||
|
// <div id="b">
|
||||||
|
// <div id="c"></div>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
//
|
||||||
|
// b.querySelector('#a div'); // Should return "c".
|
||||||
|
//
|
||||||
|
// For now, assert it's a root element.
|
||||||
|
debug_assert!(element.parent_element().is_none());
|
||||||
|
|
||||||
|
let target_vector =
|
||||||
|
if self.matching_context.scope_element.is_some() {
|
||||||
|
descendant_invalidations
|
||||||
|
} else {
|
||||||
|
self_invalidations
|
||||||
|
};
|
||||||
|
|
||||||
|
for selector in self.selector_list.0.iter() {
|
||||||
|
target_vector.push(Invalidation::new(selector, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
|
||||||
|
&mut self.matching_context
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_process_descendants(&mut self, _: E) -> bool {
|
||||||
|
if Q::should_stop_after_first_match() {
|
||||||
|
return Q::is_empty(&self.results)
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invalidated_self(&mut self, e: E) {
|
||||||
|
Q::append_element(self.results, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recursion_limit_exceeded(&mut self, _e: E) {}
|
||||||
|
fn invalidated_descendants(&mut self, _e: E, _child: E) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_all_elements<E, Q, F>(
|
||||||
|
root: E::ConcreteNode,
|
||||||
|
results: &mut Q::Output,
|
||||||
|
mut filter: F,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
Q: SelectorQuery<E>,
|
||||||
|
F: FnMut(E) -> bool,
|
||||||
|
{
|
||||||
|
for node in root.dom_descendants() {
|
||||||
|
let element = match node.as_element() {
|
||||||
|
Some(e) => e,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !filter(element) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q::append_element(results, element);
|
||||||
|
if Q::should_stop_after_first_match() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fast paths for a given selector query.
|
||||||
|
///
|
||||||
|
/// FIXME(emilio, nbp): This may very well be a good candidate for code to be
|
||||||
|
/// replaced by HolyJit :)
|
||||||
|
fn query_selector_fast<E, Q>(
|
||||||
|
root: E::ConcreteNode,
|
||||||
|
selector_list: &SelectorList<E::Impl>,
|
||||||
|
results: &mut Q::Output,
|
||||||
|
quirks_mode: QuirksMode,
|
||||||
|
) -> Result<(), ()>
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
Q: SelectorQuery<E>,
|
||||||
|
{
|
||||||
|
use selectors::parser::{Component, LocalName};
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
|
||||||
|
// We need to return elements in document order, and reordering them
|
||||||
|
// afterwards is kinda silly.
|
||||||
|
if selector_list.0.len() > 1 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let selector = &selector_list.0[0];
|
||||||
|
|
||||||
|
// Let's just care about the easy cases for now.
|
||||||
|
//
|
||||||
|
// FIXME(emilio): Blink has a fast path for classes in ancestor combinators
|
||||||
|
// that may be worth stealing.
|
||||||
|
if selector.len() > 1 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let component = selector.iter().next().unwrap();
|
||||||
|
match *component {
|
||||||
|
Component::ExplicitUniversalType => {
|
||||||
|
collect_all_elements::<E, Q, _>(root, results, |_| true)
|
||||||
|
}
|
||||||
|
Component::ID(ref id) => {
|
||||||
|
// TODO(emilio): We may want to reuse Gecko's document ID table.
|
||||||
|
let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
|
||||||
|
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||||
|
element.has_id(id, case_sensitivity)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Component::Class(ref class) => {
|
||||||
|
let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
|
||||||
|
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||||
|
element.has_class(class, case_sensitivity)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Component::LocalName(LocalName { ref name, ref lower_name }) => {
|
||||||
|
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||||
|
if element.is_html_element_in_html_document() {
|
||||||
|
element.get_local_name() == lower_name.borrow()
|
||||||
|
} else {
|
||||||
|
element.get_local_name() == name.borrow()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// TODO(emilio): More fast paths?
|
||||||
|
_ => {
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slow path for a given selector query.
|
||||||
|
fn query_selector_slow<E, Q>(
|
||||||
|
root: E::ConcreteNode,
|
||||||
|
selector_list: &SelectorList<E::Impl>,
|
||||||
|
results: &mut Q::Output,
|
||||||
|
matching_context: &mut MatchingContext<E::Impl>,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
Q: SelectorQuery<E>,
|
||||||
|
{
|
||||||
|
collect_all_elements::<E, Q, _>(root, results, |element| {
|
||||||
|
matching::matches_selector_list(selector_list, &element, matching_context)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://dom.spec.whatwg.org/#dom-parentnode-queryselector>
|
||||||
|
pub fn query_selector<E, Q>(
|
||||||
|
root: E::ConcreteNode,
|
||||||
|
selector_list: &SelectorList<E::Impl>,
|
||||||
|
results: &mut Q::Output,
|
||||||
|
quirks_mode: QuirksMode,
|
||||||
|
)
|
||||||
|
where
|
||||||
|
E: TElement,
|
||||||
|
Q: SelectorQuery<E>,
|
||||||
|
{
|
||||||
|
use invalidation::element::invalidator::TreeStyleInvalidator;
|
||||||
|
|
||||||
|
let fast_result = query_selector_fast::<E, Q>(
|
||||||
|
root,
|
||||||
|
selector_list,
|
||||||
|
results,
|
||||||
|
quirks_mode,
|
||||||
|
);
|
||||||
|
|
||||||
|
if fast_result.is_ok() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slow path: Use the invalidation machinery if we're a root, and tree
|
||||||
|
// traversal otherwise.
|
||||||
|
//
|
||||||
|
// See the comment in collect_invalidations to see why only if we're a root.
|
||||||
|
let mut nth_index_cache = NthIndexCache::default();
|
||||||
|
let mut matching_context = MatchingContext::new(
|
||||||
|
MatchingMode::Normal,
|
||||||
|
None,
|
||||||
|
Some(&mut nth_index_cache),
|
||||||
|
quirks_mode,
|
||||||
|
);
|
||||||
|
|
||||||
|
let root_element = root.as_element();
|
||||||
|
matching_context.scope_element = root_element.map(|e| e.opaque());
|
||||||
|
|
||||||
|
// The invalidation mechanism is only useful in presence of combinators.
|
||||||
|
//
|
||||||
|
// We could do that check properly here, though checking the length of the
|
||||||
|
// selectors is a good heuristic.
|
||||||
|
let invalidation_may_be_useful =
|
||||||
|
selector_list.0.iter().any(|s| s.len() > 1);
|
||||||
|
|
||||||
|
if root_element.is_some() || !invalidation_may_be_useful {
|
||||||
|
query_selector_slow::<E, Q>(
|
||||||
|
root,
|
||||||
|
selector_list,
|
||||||
|
results,
|
||||||
|
&mut matching_context,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let mut processor = QuerySelectorProcessor::<E, Q> {
|
||||||
|
results,
|
||||||
|
matching_context,
|
||||||
|
selector_list,
|
||||||
|
};
|
||||||
|
|
||||||
|
for node in root.dom_children() {
|
||||||
|
if let Some(e) = node.as_element() {
|
||||||
|
TreeStyleInvalidator::new(
|
||||||
|
e,
|
||||||
|
/* stack_limit_checker = */ None,
|
||||||
|
&mut processor,
|
||||||
|
).invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4368,8 +4368,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_forcemessagemanager: *mut nsAtom;
|
pub static nsGkAtoms_forcemessagemanager: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms16isPreloadBrowserE"]
|
#[link_name = "_ZN9nsGkAtoms16isPreloadBrowserE"]
|
||||||
pub static nsGkAtoms_isPreloadBrowser: *mut nsAtom;
|
pub static nsGkAtoms_isPreloadBrowser: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms22color_picker_availableE"]
|
|
||||||
pub static nsGkAtoms_color_picker_available: *mut nsAtom;
|
|
||||||
#[link_name = "_ZN9nsGkAtoms24scrollbar_start_backwardE"]
|
#[link_name = "_ZN9nsGkAtoms24scrollbar_start_backwardE"]
|
||||||
pub static nsGkAtoms_scrollbar_start_backward: *mut nsAtom;
|
pub static nsGkAtoms_scrollbar_start_backward: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms23scrollbar_start_forwardE"]
|
#[link_name = "_ZN9nsGkAtoms23scrollbar_start_forwardE"]
|
||||||
|
@ -4400,8 +4398,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_menubar_drag: *mut nsAtom;
|
pub static nsGkAtoms_menubar_drag: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms23swipe_animation_enabledE"]
|
#[link_name = "_ZN9nsGkAtoms23swipe_animation_enabledE"]
|
||||||
pub static nsGkAtoms_swipe_animation_enabled: *mut nsAtom;
|
pub static nsGkAtoms_swipe_animation_enabled: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms20physical_home_buttonE"]
|
|
||||||
pub static nsGkAtoms_physical_home_button: *mut nsAtom;
|
|
||||||
#[link_name = "_ZN9nsGkAtoms15windows_classicE"]
|
#[link_name = "_ZN9nsGkAtoms15windows_classicE"]
|
||||||
pub static nsGkAtoms_windows_classic: *mut nsAtom;
|
pub static nsGkAtoms_windows_classic: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms18windows_theme_aeroE"]
|
#[link_name = "_ZN9nsGkAtoms18windows_theme_aeroE"]
|
||||||
|
@ -4420,8 +4416,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_windows_theme_zune: *mut nsAtom;
|
pub static nsGkAtoms_windows_theme_zune: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms21windows_theme_genericE"]
|
#[link_name = "_ZN9nsGkAtoms21windows_theme_genericE"]
|
||||||
pub static nsGkAtoms_windows_theme_generic: *mut nsAtom;
|
pub static nsGkAtoms_windows_theme_generic: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms27_moz_color_picker_availableE"]
|
|
||||||
pub static nsGkAtoms__moz_color_picker_available: *mut nsAtom;
|
|
||||||
#[link_name = "_ZN9nsGkAtoms29_moz_scrollbar_start_backwardE"]
|
#[link_name = "_ZN9nsGkAtoms29_moz_scrollbar_start_backwardE"]
|
||||||
pub static nsGkAtoms__moz_scrollbar_start_backward: *mut nsAtom;
|
pub static nsGkAtoms__moz_scrollbar_start_backward: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms28_moz_scrollbar_start_forwardE"]
|
#[link_name = "_ZN9nsGkAtoms28_moz_scrollbar_start_forwardE"]
|
||||||
|
@ -4464,8 +4458,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms__moz_is_resource_document: *mut nsAtom;
|
pub static nsGkAtoms__moz_is_resource_document: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms28_moz_swipe_animation_enabledE"]
|
#[link_name = "_ZN9nsGkAtoms28_moz_swipe_animation_enabledE"]
|
||||||
pub static nsGkAtoms__moz_swipe_animation_enabled: *mut nsAtom;
|
pub static nsGkAtoms__moz_swipe_animation_enabled: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms25_moz_physical_home_buttonE"]
|
|
||||||
pub static nsGkAtoms__moz_physical_home_button: *mut nsAtom;
|
|
||||||
#[link_name = "_ZN9nsGkAtoms4BackE"]
|
#[link_name = "_ZN9nsGkAtoms4BackE"]
|
||||||
pub static nsGkAtoms_Back: *mut nsAtom;
|
pub static nsGkAtoms_Back: *mut nsAtom;
|
||||||
#[link_name = "_ZN9nsGkAtoms7ForwardE"]
|
#[link_name = "_ZN9nsGkAtoms7ForwardE"]
|
||||||
|
@ -9539,8 +9531,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_forcemessagemanager: *mut nsAtom;
|
pub static nsGkAtoms_forcemessagemanager: *mut nsAtom;
|
||||||
#[link_name = "?isPreloadBrowser@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?isPreloadBrowser@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
pub static nsGkAtoms_isPreloadBrowser: *mut nsAtom;
|
pub static nsGkAtoms_isPreloadBrowser: *mut nsAtom;
|
||||||
#[link_name = "?color_picker_available@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
|
||||||
pub static nsGkAtoms_color_picker_available: *mut nsAtom;
|
|
||||||
#[link_name = "?scrollbar_start_backward@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?scrollbar_start_backward@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
pub static nsGkAtoms_scrollbar_start_backward: *mut nsAtom;
|
pub static nsGkAtoms_scrollbar_start_backward: *mut nsAtom;
|
||||||
#[link_name = "?scrollbar_start_forward@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?scrollbar_start_forward@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
|
@ -9571,8 +9561,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_menubar_drag: *mut nsAtom;
|
pub static nsGkAtoms_menubar_drag: *mut nsAtom;
|
||||||
#[link_name = "?swipe_animation_enabled@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?swipe_animation_enabled@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
pub static nsGkAtoms_swipe_animation_enabled: *mut nsAtom;
|
pub static nsGkAtoms_swipe_animation_enabled: *mut nsAtom;
|
||||||
#[link_name = "?physical_home_button@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
|
||||||
pub static nsGkAtoms_physical_home_button: *mut nsAtom;
|
|
||||||
#[link_name = "?windows_classic@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?windows_classic@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
pub static nsGkAtoms_windows_classic: *mut nsAtom;
|
pub static nsGkAtoms_windows_classic: *mut nsAtom;
|
||||||
#[link_name = "?windows_theme_aero@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?windows_theme_aero@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
|
@ -9591,8 +9579,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_windows_theme_zune: *mut nsAtom;
|
pub static nsGkAtoms_windows_theme_zune: *mut nsAtom;
|
||||||
#[link_name = "?windows_theme_generic@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?windows_theme_generic@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
pub static nsGkAtoms_windows_theme_generic: *mut nsAtom;
|
pub static nsGkAtoms_windows_theme_generic: *mut nsAtom;
|
||||||
#[link_name = "?_moz_color_picker_available@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
|
||||||
pub static nsGkAtoms__moz_color_picker_available: *mut nsAtom;
|
|
||||||
#[link_name = "?_moz_scrollbar_start_backward@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?_moz_scrollbar_start_backward@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
pub static nsGkAtoms__moz_scrollbar_start_backward: *mut nsAtom;
|
pub static nsGkAtoms__moz_scrollbar_start_backward: *mut nsAtom;
|
||||||
#[link_name = "?_moz_scrollbar_start_forward@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?_moz_scrollbar_start_forward@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
|
@ -9635,8 +9621,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms__moz_is_resource_document: *mut nsAtom;
|
pub static nsGkAtoms__moz_is_resource_document: *mut nsAtom;
|
||||||
#[link_name = "?_moz_swipe_animation_enabled@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?_moz_swipe_animation_enabled@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
pub static nsGkAtoms__moz_swipe_animation_enabled: *mut nsAtom;
|
pub static nsGkAtoms__moz_swipe_animation_enabled: *mut nsAtom;
|
||||||
#[link_name = "?_moz_physical_home_button@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
|
||||||
pub static nsGkAtoms__moz_physical_home_button: *mut nsAtom;
|
|
||||||
#[link_name = "?Back@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?Back@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
pub static nsGkAtoms_Back: *mut nsAtom;
|
pub static nsGkAtoms_Back: *mut nsAtom;
|
||||||
#[link_name = "?Forward@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
#[link_name = "?Forward@nsGkAtoms@@2PEAVnsAtom@@EA"]
|
||||||
|
@ -14710,8 +14694,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_forcemessagemanager: *mut nsAtom;
|
pub static nsGkAtoms_forcemessagemanager: *mut nsAtom;
|
||||||
#[link_name = "\x01?isPreloadBrowser@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?isPreloadBrowser@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
pub static nsGkAtoms_isPreloadBrowser: *mut nsAtom;
|
pub static nsGkAtoms_isPreloadBrowser: *mut nsAtom;
|
||||||
#[link_name = "\x01?color_picker_available@nsGkAtoms@@2PAVnsAtom@@A"]
|
|
||||||
pub static nsGkAtoms_color_picker_available: *mut nsAtom;
|
|
||||||
#[link_name = "\x01?scrollbar_start_backward@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?scrollbar_start_backward@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
pub static nsGkAtoms_scrollbar_start_backward: *mut nsAtom;
|
pub static nsGkAtoms_scrollbar_start_backward: *mut nsAtom;
|
||||||
#[link_name = "\x01?scrollbar_start_forward@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?scrollbar_start_forward@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
|
@ -14742,8 +14724,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_menubar_drag: *mut nsAtom;
|
pub static nsGkAtoms_menubar_drag: *mut nsAtom;
|
||||||
#[link_name = "\x01?swipe_animation_enabled@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?swipe_animation_enabled@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
pub static nsGkAtoms_swipe_animation_enabled: *mut nsAtom;
|
pub static nsGkAtoms_swipe_animation_enabled: *mut nsAtom;
|
||||||
#[link_name = "\x01?physical_home_button@nsGkAtoms@@2PAVnsAtom@@A"]
|
|
||||||
pub static nsGkAtoms_physical_home_button: *mut nsAtom;
|
|
||||||
#[link_name = "\x01?windows_classic@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?windows_classic@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
pub static nsGkAtoms_windows_classic: *mut nsAtom;
|
pub static nsGkAtoms_windows_classic: *mut nsAtom;
|
||||||
#[link_name = "\x01?windows_theme_aero@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?windows_theme_aero@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
|
@ -14762,8 +14742,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms_windows_theme_zune: *mut nsAtom;
|
pub static nsGkAtoms_windows_theme_zune: *mut nsAtom;
|
||||||
#[link_name = "\x01?windows_theme_generic@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?windows_theme_generic@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
pub static nsGkAtoms_windows_theme_generic: *mut nsAtom;
|
pub static nsGkAtoms_windows_theme_generic: *mut nsAtom;
|
||||||
#[link_name = "\x01?_moz_color_picker_available@nsGkAtoms@@2PAVnsAtom@@A"]
|
|
||||||
pub static nsGkAtoms__moz_color_picker_available: *mut nsAtom;
|
|
||||||
#[link_name = "\x01?_moz_scrollbar_start_backward@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?_moz_scrollbar_start_backward@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
pub static nsGkAtoms__moz_scrollbar_start_backward: *mut nsAtom;
|
pub static nsGkAtoms__moz_scrollbar_start_backward: *mut nsAtom;
|
||||||
#[link_name = "\x01?_moz_scrollbar_start_forward@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?_moz_scrollbar_start_forward@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
|
@ -14806,8 +14784,6 @@ cfg_if! {
|
||||||
pub static nsGkAtoms__moz_is_resource_document: *mut nsAtom;
|
pub static nsGkAtoms__moz_is_resource_document: *mut nsAtom;
|
||||||
#[link_name = "\x01?_moz_swipe_animation_enabled@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?_moz_swipe_animation_enabled@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
pub static nsGkAtoms__moz_swipe_animation_enabled: *mut nsAtom;
|
pub static nsGkAtoms__moz_swipe_animation_enabled: *mut nsAtom;
|
||||||
#[link_name = "\x01?_moz_physical_home_button@nsGkAtoms@@2PAVnsAtom@@A"]
|
|
||||||
pub static nsGkAtoms__moz_physical_home_button: *mut nsAtom;
|
|
||||||
#[link_name = "\x01?Back@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?Back@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
pub static nsGkAtoms_Back: *mut nsAtom;
|
pub static nsGkAtoms_Back: *mut nsAtom;
|
||||||
#[link_name = "\x01?Forward@nsGkAtoms@@2PAVnsAtom@@A"]
|
#[link_name = "\x01?Forward@nsGkAtoms@@2PAVnsAtom@@A"]
|
||||||
|
@ -19884,8 +19860,6 @@ macro_rules! atom {
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_forcemessagemanager as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_forcemessagemanager as *mut _) } };
|
||||||
("isPreloadBrowser") =>
|
("isPreloadBrowser") =>
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_isPreloadBrowser as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_isPreloadBrowser as *mut _) } };
|
||||||
("color-picker-available") =>
|
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_color_picker_available as *mut _) } };
|
|
||||||
("scrollbar-start-backward") =>
|
("scrollbar-start-backward") =>
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_scrollbar_start_backward as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_scrollbar_start_backward as *mut _) } };
|
||||||
("scrollbar-start-forward") =>
|
("scrollbar-start-forward") =>
|
||||||
|
@ -19916,8 +19890,6 @@ macro_rules! atom {
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_menubar_drag as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_menubar_drag as *mut _) } };
|
||||||
("swipe-animation-enabled") =>
|
("swipe-animation-enabled") =>
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_swipe_animation_enabled as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_swipe_animation_enabled as *mut _) } };
|
||||||
("physical-home-button") =>
|
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_physical_home_button as *mut _) } };
|
|
||||||
("windows-classic") =>
|
("windows-classic") =>
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_windows_classic as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_windows_classic as *mut _) } };
|
||||||
("windows-theme-aero") =>
|
("windows-theme-aero") =>
|
||||||
|
@ -19936,8 +19908,6 @@ macro_rules! atom {
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_windows_theme_zune as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_windows_theme_zune as *mut _) } };
|
||||||
("windows-theme-generic") =>
|
("windows-theme-generic") =>
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_windows_theme_generic as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_windows_theme_generic as *mut _) } };
|
||||||
("-moz-color-picker-available") =>
|
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_color_picker_available as *mut _) } };
|
|
||||||
("-moz-scrollbar-start-backward") =>
|
("-moz-scrollbar-start-backward") =>
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_scrollbar_start_backward as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_scrollbar_start_backward as *mut _) } };
|
||||||
("-moz-scrollbar-start-forward") =>
|
("-moz-scrollbar-start-forward") =>
|
||||||
|
@ -19980,8 +19950,6 @@ macro_rules! atom {
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_is_resource_document as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_is_resource_document as *mut _) } };
|
||||||
("-moz-swipe-animation-enabled") =>
|
("-moz-swipe-animation-enabled") =>
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_swipe_animation_enabled as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_swipe_animation_enabled as *mut _) } };
|
||||||
("-moz-physical-home-button") =>
|
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms__moz_physical_home_button as *mut _) } };
|
|
||||||
("Back") =>
|
("Back") =>
|
||||||
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_Back as *mut _) } };
|
{ unsafe { $crate::string_cache::atom_macro::atom_from_static($crate::string_cache::atom_macro::nsGkAtoms_Back as *mut _) } };
|
||||||
("Forward") =>
|
("Forward") =>
|
||||||
|
|
|
@ -23,6 +23,7 @@ use gecko_bindings::structs::ServoRawOffsetArc;
|
||||||
use gecko_bindings::structs::nsIContent;
|
use gecko_bindings::structs::nsIContent;
|
||||||
use gecko_bindings::structs::nsIDocument;
|
use gecko_bindings::structs::nsIDocument;
|
||||||
use gecko_bindings::structs::nsIDocument_DocumentTheme;
|
use gecko_bindings::structs::nsIDocument_DocumentTheme;
|
||||||
|
use gecko_bindings::structs::nsSimpleContentList;
|
||||||
use gecko_bindings::structs::RawGeckoAnimationPropertySegment;
|
use gecko_bindings::structs::RawGeckoAnimationPropertySegment;
|
||||||
use gecko_bindings::structs::RawGeckoComputedTiming;
|
use gecko_bindings::structs::RawGeckoComputedTiming;
|
||||||
use gecko_bindings::structs::RawGeckoCSSPropertyIDList;
|
use gecko_bindings::structs::RawGeckoCSSPropertyIDList;
|
||||||
|
@ -75,6 +76,7 @@ use gecko_bindings::structs::nsCSSFontFaceRule;
|
||||||
use gecko_bindings::structs::nsCSSKeyword;
|
use gecko_bindings::structs::nsCSSKeyword;
|
||||||
use gecko_bindings::structs::nsCSSPropertyID;
|
use gecko_bindings::structs::nsCSSPropertyID;
|
||||||
use gecko_bindings::structs::nsCSSPropertyIDSet;
|
use gecko_bindings::structs::nsCSSPropertyIDSet;
|
||||||
|
use gecko_bindings::structs::nsCSSRect;
|
||||||
use gecko_bindings::structs::nsCSSShadowArray;
|
use gecko_bindings::structs::nsCSSShadowArray;
|
||||||
use gecko_bindings::structs::nsCSSUnit;
|
use gecko_bindings::structs::nsCSSUnit;
|
||||||
use gecko_bindings::structs::nsCSSValue;
|
use gecko_bindings::structs::nsCSSValue;
|
||||||
|
@ -2129,6 +2131,17 @@ extern "C" {
|
||||||
arg2: RawServoSelectorListBorrowed)
|
arg2: RawServoSelectorListBorrowed)
|
||||||
-> *const RawGeckoElement;
|
-> *const RawGeckoElement;
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Servo_SelectorList_QueryFirst(arg1: RawGeckoNodeBorrowed,
|
||||||
|
arg2: RawServoSelectorListBorrowed)
|
||||||
|
-> *const RawGeckoElement;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Servo_SelectorList_QueryAll(arg1: RawGeckoNodeBorrowed,
|
||||||
|
arg2: RawServoSelectorListBorrowed,
|
||||||
|
content_list:
|
||||||
|
*mut nsSimpleContentList);
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Servo_StyleSet_AddSizeOfExcludingThis(malloc_size_of: MallocSizeOf,
|
pub fn Servo_StyleSet_AddSizeOfExcludingThis(malloc_size_of: MallocSizeOf,
|
||||||
malloc_enclosing_size_of:
|
malloc_enclosing_size_of:
|
||||||
|
@ -2733,7 +2746,8 @@ extern "C" {
|
||||||
pub fn Servo_DeclarationBlock_RemovePropertyById(declarations:
|
pub fn Servo_DeclarationBlock_RemovePropertyById(declarations:
|
||||||
RawServoDeclarationBlockBorrowed,
|
RawServoDeclarationBlockBorrowed,
|
||||||
property:
|
property:
|
||||||
nsCSSPropertyID) -> bool;
|
nsCSSPropertyID)
|
||||||
|
-> bool;
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Servo_DeclarationBlock_HasCSSWideKeyword(declarations:
|
pub fn Servo_DeclarationBlock_HasCSSWideKeyword(declarations:
|
||||||
|
@ -3075,6 +3089,19 @@ extern "C" {
|
||||||
*const ServoRawOffsetArc<RustString>)
|
*const ServoRawOffsetArc<RustString>)
|
||||||
-> ServoRawOffsetArc<RustString>;
|
-> ServoRawOffsetArc<RustString>;
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Servo_IsValidCSSColor(value: *const nsAString) -> bool;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Servo_ComputeColor(set: RawServoStyleSetBorrowedOrNull,
|
||||||
|
current_color: nscolor, value: *const nsAString,
|
||||||
|
result_color: *mut nscolor) -> bool;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Servo_ParseIntersectionObserverRootMargin(value: *const nsAString,
|
||||||
|
result: *mut nsCSSRect)
|
||||||
|
-> bool;
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_CreateCSSErrorReporter(sheet: *mut ServoStyleSheet,
|
pub fn Gecko_CreateCSSErrorReporter(sheet: *mut ServoStyleSheet,
|
||||||
loader: *mut Loader, uri: *mut nsIURI)
|
loader: *mut Loader, uri: *mut nsIURI)
|
||||||
|
@ -3102,3 +3129,8 @@ extern "C" {
|
||||||
sourceLen: u32, lineNumber: u32,
|
sourceLen: u32, lineNumber: u32,
|
||||||
colNumber: u32);
|
colNumber: u32);
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_ContentList_AppendAll(aContentList: *mut nsSimpleContentList,
|
||||||
|
aElements: *mut *const RawGeckoElement,
|
||||||
|
aLength: usize);
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,7 +17,7 @@
|
||||||
use CaseSensitivityExt;
|
use CaseSensitivityExt;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use applicable_declarations::ApplicableDeclarationBlock;
|
use applicable_declarations::ApplicableDeclarationBlock;
|
||||||
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
|
use atomic_refcell::{AtomicRefCell, AtomicRef, AtomicRefMut};
|
||||||
use context::{QuirksMode, SharedStyleContext, PostAnimationTasks, UpdateAnimationsTasks};
|
use context::{QuirksMode, SharedStyleContext, PostAnimationTasks, UpdateAnimationsTasks};
|
||||||
use data::ElementData;
|
use data::ElementData;
|
||||||
use dom::{LayoutIterator, NodeInfo, TElement, TNode};
|
use dom::{LayoutIterator, NodeInfo, TElement, TNode};
|
||||||
|
@ -104,6 +104,12 @@ use stylist::Stylist;
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct GeckoNode<'ln>(pub &'ln RawGeckoNode);
|
pub struct GeckoNode<'ln>(pub &'ln RawGeckoNode);
|
||||||
|
|
||||||
|
impl<'ln> PartialEq for GeckoNode<'ln> {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.0 as *const _ == other.0 as *const _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'ln> fmt::Debug for GeckoNode<'ln> {
|
impl<'ln> fmt::Debug for GeckoNode<'ln> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if let Some(el) = self.as_element() {
|
if let Some(el) = self.as_element() {
|
||||||
|
@ -148,6 +154,12 @@ impl<'ln> GeckoNode<'ln> {
|
||||||
(self.0).mBoolFlags
|
(self.0).mBoolFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Owner document quirks mode getter.
|
||||||
|
#[inline]
|
||||||
|
pub fn owner_document_quirks_mode(&self) -> QuirksMode {
|
||||||
|
self.owner_doc().mCompatMode.into()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_bool_flag(&self, flag: nsINode_BooleanFlag) -> bool {
|
fn get_bool_flag(&self, flag: nsINode_BooleanFlag) -> bool {
|
||||||
self.bool_flags() & (1u32 << flag as u32) != 0
|
self.bool_flags() & (1u32 << flag as u32) != 0
|
||||||
|
@ -355,9 +367,9 @@ impl<'lb> GeckoXBLBinding<'lb> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn each_xbl_stylist<F>(self, f: &mut F)
|
fn each_xbl_stylist<F>(&self, f: &mut F)
|
||||||
where
|
where
|
||||||
F: FnMut(&Stylist),
|
F: FnMut(AtomicRef<'lb, Stylist>),
|
||||||
{
|
{
|
||||||
if let Some(base) = self.base_binding() {
|
if let Some(base) = self.base_binding() {
|
||||||
base.each_xbl_stylist(f);
|
base.each_xbl_stylist(f);
|
||||||
|
@ -369,7 +381,7 @@ impl<'lb> GeckoXBLBinding<'lb> {
|
||||||
|
|
||||||
if let Some(raw_data) = raw_data {
|
if let Some(raw_data) = raw_data {
|
||||||
let data = PerDocumentStyleData::from_ffi(&*raw_data).borrow();
|
let data = PerDocumentStyleData::from_ffi(&*raw_data).borrow();
|
||||||
f(&data.stylist);
|
f(AtomicRef::map(data, |d| &d.stylist));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -476,7 +488,7 @@ impl<'le> GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_xbl_binding(&self) -> Option<GeckoXBLBinding> {
|
fn get_xbl_binding(&self) -> Option<GeckoXBLBinding<'le>> {
|
||||||
if self.flags() & (structs::NODE_MAY_BE_IN_BINDING_MNGR as u32) == 0 {
|
if self.flags() & (structs::NODE_MAY_BE_IN_BINDING_MNGR as u32) == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -485,7 +497,7 @@ impl<'le> GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_xbl_binding_with_content(&self) -> Option<GeckoXBLBinding> {
|
fn get_xbl_binding_with_content(&self) -> Option<GeckoXBLBinding<'le>> {
|
||||||
self.get_xbl_binding()
|
self.get_xbl_binding()
|
||||||
.and_then(|b| b.get_binding_with_content())
|
.and_then(|b| b.get_binding_with_content())
|
||||||
}
|
}
|
||||||
|
@ -625,8 +637,9 @@ impl<'le> GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Owner document quirks mode getter.
|
/// Owner document quirks mode getter.
|
||||||
|
#[inline]
|
||||||
pub fn owner_document_quirks_mode(&self) -> QuirksMode {
|
pub fn owner_document_quirks_mode(&self) -> QuirksMode {
|
||||||
self.as_node().owner_doc().mCompatMode.into()
|
self.as_node().owner_document_quirks_mode()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Only safe to call on the main thread, with exclusive access to the element and
|
/// Only safe to call on the main thread, with exclusive access to the element and
|
||||||
|
@ -1246,9 +1259,10 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
self.may_have_animations() && unsafe { Gecko_ElementHasCSSTransitions(self.0) }
|
self.may_have_animations() && unsafe { Gecko_ElementHasCSSTransitions(self.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn each_xbl_stylist<F>(&self, mut f: F) -> bool
|
fn each_xbl_stylist<'a, F>(&self, mut f: F) -> bool
|
||||||
where
|
where
|
||||||
F: FnMut(&Stylist),
|
'le: 'a,
|
||||||
|
F: FnMut(AtomicRef<'a, Stylist>),
|
||||||
{
|
{
|
||||||
// Walk the binding scope chain, starting with the binding attached to
|
// Walk the binding scope chain, starting with the binding attached to
|
||||||
// our content, up till we run out of scopes or we get cut off.
|
// our content, up till we run out of scopes or we get cut off.
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
//! changes.
|
//! changes.
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
|
use atomic_refcell::AtomicRef;
|
||||||
use context::{QuirksMode, SharedStyleContext};
|
use context::{QuirksMode, SharedStyleContext};
|
||||||
use data::ElementData;
|
use data::ElementData;
|
||||||
use dom::TElement;
|
use dom::TElement;
|
||||||
|
@ -21,6 +22,8 @@ use selectors::attr::CaseSensitivity;
|
||||||
use selectors::matching::{MatchingContext, MatchingMode, VisitedHandlingMode};
|
use selectors::matching::{MatchingContext, MatchingMode, VisitedHandlingMode};
|
||||||
use selectors::matching::matches_selector;
|
use selectors::matching::matches_selector;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use stylesheets::origin::{Origin, OriginSet};
|
||||||
|
use stylist::Stylist;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum VisitedDependent {
|
enum VisitedDependent {
|
||||||
|
@ -29,7 +32,7 @@ enum VisitedDependent {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The collector implementation.
|
/// The collector implementation.
|
||||||
struct Collector<'a, 'b: 'a, E>
|
struct Collector<'a, 'b: 'a, 'selectors: 'a, E>
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
{
|
{
|
||||||
|
@ -44,31 +47,52 @@ where
|
||||||
classes_removed: &'a SmallVec<[Atom; 8]>,
|
classes_removed: &'a SmallVec<[Atom; 8]>,
|
||||||
classes_added: &'a SmallVec<[Atom; 8]>,
|
classes_added: &'a SmallVec<[Atom; 8]>,
|
||||||
state_changes: ElementState,
|
state_changes: ElementState,
|
||||||
descendant_invalidations: &'a mut InvalidationVector,
|
descendant_invalidations: &'a mut InvalidationVector<'selectors>,
|
||||||
sibling_invalidations: &'a mut InvalidationVector,
|
sibling_invalidations: &'a mut InvalidationVector<'selectors>,
|
||||||
invalidates_self: bool,
|
invalidates_self: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An invalidation processor for style changes due to state and attribute
|
/// An invalidation processor for style changes due to state and attribute
|
||||||
/// changes.
|
/// changes.
|
||||||
pub struct StateAndAttrInvalidationProcessor<'a, 'b: 'a, E> {
|
pub struct StateAndAttrInvalidationProcessor<'a, 'b: 'a, E: TElement> {
|
||||||
shared_context: &'a SharedStyleContext<'b>,
|
shared_context: &'a SharedStyleContext<'b>,
|
||||||
|
xbl_stylists: &'a [AtomicRef<'b, Stylist>],
|
||||||
|
cut_off_inheritance: bool,
|
||||||
element: E,
|
element: E,
|
||||||
data: &'a mut ElementData,
|
data: &'a mut ElementData,
|
||||||
|
matching_context: MatchingContext<'a, E::Impl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b: 'a, E> StateAndAttrInvalidationProcessor<'a, 'b, E> {
|
impl<'a, 'b: 'a, E: TElement> StateAndAttrInvalidationProcessor<'a, 'b, E> {
|
||||||
/// Creates a new StateAndAttrInvalidationProcessor.
|
/// Creates a new StateAndAttrInvalidationProcessor.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
shared_context: &'a SharedStyleContext<'b>,
|
shared_context: &'a SharedStyleContext<'b>,
|
||||||
|
xbl_stylists: &'a [AtomicRef<'b, Stylist>],
|
||||||
|
cut_off_inheritance: bool,
|
||||||
element: E,
|
element: E,
|
||||||
data: &'a mut ElementData,
|
data: &'a mut ElementData,
|
||||||
|
nth_index_cache: Option<&'a mut NthIndexCache>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self { shared_context, element, data }
|
let matching_context = MatchingContext::new_for_visited(
|
||||||
|
MatchingMode::Normal,
|
||||||
|
None,
|
||||||
|
nth_index_cache,
|
||||||
|
VisitedHandlingMode::AllLinksVisitedAndUnvisited,
|
||||||
|
shared_context.quirks_mode(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
shared_context,
|
||||||
|
xbl_stylists,
|
||||||
|
cut_off_inheritance,
|
||||||
|
element,
|
||||||
|
data,
|
||||||
|
matching_context,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b: 'a, E> InvalidationProcessor<E> for StateAndAttrInvalidationProcessor<'a, 'b, E>
|
impl<'a, 'b: 'a, E: 'a> InvalidationProcessor<'a, E> for StateAndAttrInvalidationProcessor<'a, 'b, E>
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
{
|
{
|
||||||
|
@ -77,16 +101,18 @@ where
|
||||||
/// content being generated.
|
/// content being generated.
|
||||||
fn invalidates_on_eager_pseudo_element(&self) -> bool { true }
|
fn invalidates_on_eager_pseudo_element(&self) -> bool { true }
|
||||||
|
|
||||||
|
fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> {
|
||||||
|
&mut self.matching_context
|
||||||
|
}
|
||||||
|
|
||||||
fn collect_invalidations(
|
fn collect_invalidations(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: E,
|
element: E,
|
||||||
nth_index_cache: Option<&mut NthIndexCache>,
|
_self_invalidations: &mut InvalidationVector<'a>,
|
||||||
quirks_mode: QuirksMode,
|
descendant_invalidations: &mut InvalidationVector<'a>,
|
||||||
descendant_invalidations: &mut InvalidationVector,
|
sibling_invalidations: &mut InvalidationVector<'a>,
|
||||||
sibling_invalidations: &mut InvalidationVector,
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug_assert!(element.has_snapshot(), "Why bothering?");
|
debug_assert!(element.has_snapshot(), "Why bothering?");
|
||||||
debug_assert_eq!(quirks_mode, self.shared_context.quirks_mode(), "How exactly?");
|
|
||||||
|
|
||||||
let wrapper =
|
let wrapper =
|
||||||
ElementWrapper::new(element, &*self.shared_context.snapshot_map);
|
ElementWrapper::new(element, &*self.shared_context.snapshot_map);
|
||||||
|
@ -149,11 +175,11 @@ where
|
||||||
let mut collector = Collector {
|
let mut collector = Collector {
|
||||||
wrapper,
|
wrapper,
|
||||||
lookup_element,
|
lookup_element,
|
||||||
nth_index_cache,
|
|
||||||
state_changes,
|
state_changes,
|
||||||
element,
|
element,
|
||||||
snapshot: &snapshot,
|
snapshot: &snapshot,
|
||||||
quirks_mode: self.shared_context.quirks_mode(),
|
quirks_mode: self.shared_context.quirks_mode(),
|
||||||
|
nth_index_cache: self.matching_context.nth_index_cache.as_mut().map(|c| &mut **c),
|
||||||
removed_id: id_removed.as_ref(),
|
removed_id: id_removed.as_ref(),
|
||||||
added_id: id_added.as_ref(),
|
added_id: id_added.as_ref(),
|
||||||
classes_removed: &classes_removed,
|
classes_removed: &classes_removed,
|
||||||
|
@ -163,24 +189,27 @@ where
|
||||||
invalidates_self: false,
|
invalidates_self: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.shared_context.stylist.each_invalidation_map(|invalidation_map| {
|
let document_origins = if self.cut_off_inheritance {
|
||||||
|
Origin::UserAgent.into()
|
||||||
|
} else {
|
||||||
|
OriginSet::all()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.shared_context.stylist.each_invalidation_map(|invalidation_map, origin| {
|
||||||
|
if document_origins.contains(origin.into()) {
|
||||||
collector.collect_dependencies_in_invalidation_map(invalidation_map);
|
collector.collect_dependencies_in_invalidation_map(invalidation_map);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO(emilio): Consider storing dependencies from the UA sheet in
|
for stylist in self.xbl_stylists {
|
||||||
// a different map. If we do that, we can skip the stuff on the
|
|
||||||
// shared stylist iff cut_off_inheritance is true, and we can look
|
|
||||||
// just at that map.
|
|
||||||
let _cut_off_inheritance =
|
|
||||||
element.each_xbl_stylist(|stylist| {
|
|
||||||
// FIXME(emilio): Replace with assert / remove when we
|
// FIXME(emilio): Replace with assert / remove when we
|
||||||
// figure out what to do with the quirks mode mismatches
|
// figure out what to do with the quirks mode mismatches
|
||||||
// (that is, when bug 1406875 is properly fixed).
|
// (that is, when bug 1406875 is properly fixed).
|
||||||
collector.quirks_mode = stylist.quirks_mode();
|
collector.quirks_mode = stylist.quirks_mode();
|
||||||
stylist.each_invalidation_map(|invalidation_map| {
|
stylist.each_invalidation_map(|invalidation_map, _| {
|
||||||
collector.collect_dependencies_in_invalidation_map(invalidation_map);
|
collector.collect_dependencies_in_invalidation_map(invalidation_map);
|
||||||
});
|
})
|
||||||
});
|
}
|
||||||
|
|
||||||
collector.invalidates_self
|
collector.invalidates_self
|
||||||
};
|
};
|
||||||
|
@ -247,13 +276,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, E> Collector<'a, 'b, E>
|
impl<'a, 'b, 'selectors, E> Collector<'a, 'b, 'selectors, E>
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
|
'selectors: 'a,
|
||||||
{
|
{
|
||||||
fn collect_dependencies_in_invalidation_map(
|
fn collect_dependencies_in_invalidation_map(
|
||||||
&mut self,
|
&mut self,
|
||||||
map: &InvalidationMap,
|
map: &'selectors InvalidationMap,
|
||||||
) {
|
) {
|
||||||
let quirks_mode = self.quirks_mode;
|
let quirks_mode = self.quirks_mode;
|
||||||
let removed_id = self.removed_id;
|
let removed_id = self.removed_id;
|
||||||
|
@ -304,7 +334,7 @@ where
|
||||||
|
|
||||||
fn collect_dependencies_in_map(
|
fn collect_dependencies_in_map(
|
||||||
&mut self,
|
&mut self,
|
||||||
map: &SelectorMap<Dependency>,
|
map: &'selectors SelectorMap<Dependency>,
|
||||||
) {
|
) {
|
||||||
map.lookup_with_additional(
|
map.lookup_with_additional(
|
||||||
self.lookup_element,
|
self.lookup_element,
|
||||||
|
@ -320,7 +350,7 @@ where
|
||||||
|
|
||||||
fn collect_state_dependencies(
|
fn collect_state_dependencies(
|
||||||
&mut self,
|
&mut self,
|
||||||
map: &SelectorMap<StateDependency>,
|
map: &'selectors SelectorMap<StateDependency>,
|
||||||
state_changes: ElementState,
|
state_changes: ElementState,
|
||||||
) {
|
) {
|
||||||
map.lookup_with_additional(
|
map.lookup_with_additional(
|
||||||
|
@ -404,7 +434,7 @@ where
|
||||||
|
|
||||||
fn scan_dependency(
|
fn scan_dependency(
|
||||||
&mut self,
|
&mut self,
|
||||||
dependency: &Dependency,
|
dependency: &'selectors Dependency,
|
||||||
is_visited_dependent: VisitedDependent,
|
is_visited_dependent: VisitedDependent,
|
||||||
) {
|
) {
|
||||||
debug!("TreeStyleInvalidator::scan_dependency({:?}, {:?}, {:?})",
|
debug!("TreeStyleInvalidator::scan_dependency({:?}, {:?}, {:?})",
|
||||||
|
@ -457,7 +487,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn note_dependency(&mut self, dependency: &Dependency) {
|
fn note_dependency(&mut self, dependency: &'selectors Dependency) {
|
||||||
if dependency.affects_self() {
|
if dependency.affects_self() {
|
||||||
self.invalidates_self = true;
|
self.invalidates_self = true;
|
||||||
}
|
}
|
||||||
|
@ -467,14 +497,14 @@ where
|
||||||
debug_assert_ne!(dependency.selector_offset, dependency.selector.len());
|
debug_assert_ne!(dependency.selector_offset, dependency.selector.len());
|
||||||
debug_assert!(!dependency.affects_later_siblings());
|
debug_assert!(!dependency.affects_later_siblings());
|
||||||
self.descendant_invalidations.push(Invalidation::new(
|
self.descendant_invalidations.push(Invalidation::new(
|
||||||
dependency.selector.clone(),
|
&dependency.selector,
|
||||||
dependency.selector.len() - dependency.selector_offset + 1,
|
dependency.selector.len() - dependency.selector_offset + 1,
|
||||||
));
|
));
|
||||||
} else if dependency.affects_later_siblings() {
|
} else if dependency.affects_later_siblings() {
|
||||||
debug_assert_ne!(dependency.selector_offset, 0);
|
debug_assert_ne!(dependency.selector_offset, 0);
|
||||||
debug_assert_ne!(dependency.selector_offset, dependency.selector.len());
|
debug_assert_ne!(dependency.selector_offset, dependency.selector.len());
|
||||||
self.sibling_invalidations.push(Invalidation::new(
|
self.sibling_invalidations.push(Invalidation::new(
|
||||||
dependency.selector.clone(),
|
&dependency.selector,
|
||||||
dependency.selector.len() - dependency.selector_offset + 1,
|
dependency.selector.len() - dependency.selector_offset + 1,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,14 @@
|
||||||
use context::StackLimitChecker;
|
use context::StackLimitChecker;
|
||||||
use dom::{TElement, TNode};
|
use dom::{TElement, TNode};
|
||||||
use selector_parser::SelectorImpl;
|
use selector_parser::SelectorImpl;
|
||||||
use selectors::NthIndexCache;
|
use selectors::matching::{CompoundSelectorMatchingResult, MatchingContext};
|
||||||
use selectors::matching::{MatchingContext, MatchingMode, QuirksMode, VisitedHandlingMode};
|
|
||||||
use selectors::matching::CompoundSelectorMatchingResult;
|
|
||||||
use selectors::matching::matches_compound_selector;
|
use selectors::matching::matches_compound_selector;
|
||||||
use selectors::parser::{Combinator, Component, Selector};
|
use selectors::parser::{Combinator, Component, Selector};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// A trait to abstract the collection of invalidations for a given pass.
|
/// A trait to abstract the collection of invalidations for a given pass.
|
||||||
pub trait InvalidationProcessor<E>
|
pub trait InvalidationProcessor<'a, E>
|
||||||
where
|
where
|
||||||
E: TElement,
|
E: TElement,
|
||||||
{
|
{
|
||||||
|
@ -26,16 +24,23 @@ where
|
||||||
/// that would originate it.
|
/// that would originate it.
|
||||||
fn invalidates_on_eager_pseudo_element(&self) -> bool { false }
|
fn invalidates_on_eager_pseudo_element(&self) -> bool { false }
|
||||||
|
|
||||||
|
/// Whether the invalidation processor only cares about light-tree
|
||||||
|
/// descendants of a given element, that is, doesn't invalidate
|
||||||
|
/// pseudo-elements, NAC, or XBL anon content.
|
||||||
|
fn light_tree_only(&self) -> bool { false }
|
||||||
|
|
||||||
|
/// The matching context that should be used to process invalidations.
|
||||||
|
fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl>;
|
||||||
|
|
||||||
/// Collect invalidations for a given element's descendants and siblings.
|
/// Collect invalidations for a given element's descendants and siblings.
|
||||||
///
|
///
|
||||||
/// Returns whether the element itself was invalidated.
|
/// Returns whether the element itself was invalidated.
|
||||||
fn collect_invalidations(
|
fn collect_invalidations(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: E,
|
element: E,
|
||||||
nth_index_cache: Option<&mut NthIndexCache>,
|
self_invalidations: &mut InvalidationVector<'a>,
|
||||||
quirks_mode: QuirksMode,
|
descendant_invalidations: &mut InvalidationVector<'a>,
|
||||||
descendant_invalidations: &mut InvalidationVector,
|
sibling_invalidations: &mut InvalidationVector<'a>,
|
||||||
sibling_invalidations: &mut InvalidationVector,
|
|
||||||
) -> bool;
|
) -> bool;
|
||||||
|
|
||||||
/// Returns whether the invalidation process should process the descendants
|
/// Returns whether the invalidation process should process the descendants
|
||||||
|
@ -55,20 +60,20 @@ where
|
||||||
|
|
||||||
/// The struct that takes care of encapsulating all the logic on where and how
|
/// The struct that takes care of encapsulating all the logic on where and how
|
||||||
/// element styles need to be invalidated.
|
/// element styles need to be invalidated.
|
||||||
pub struct TreeStyleInvalidator<'a, E, P: 'a>
|
pub struct TreeStyleInvalidator<'a, 'b, E, P: 'a>
|
||||||
where
|
where
|
||||||
|
'b: 'a,
|
||||||
E: TElement,
|
E: TElement,
|
||||||
P: InvalidationProcessor<E>
|
P: InvalidationProcessor<'b, E>,
|
||||||
{
|
{
|
||||||
element: E,
|
element: E,
|
||||||
quirks_mode: QuirksMode,
|
|
||||||
stack_limit_checker: Option<&'a StackLimitChecker>,
|
stack_limit_checker: Option<&'a StackLimitChecker>,
|
||||||
nth_index_cache: Option<&'a mut NthIndexCache>,
|
|
||||||
processor: &'a mut P,
|
processor: &'a mut P,
|
||||||
|
_marker: ::std::marker::PhantomData<&'b ()>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A vector of invalidations, optimized for small invalidation sets.
|
/// A vector of invalidations, optimized for small invalidation sets.
|
||||||
pub type InvalidationVector = SmallVec<[Invalidation; 10]>;
|
pub type InvalidationVector<'a> = SmallVec<[Invalidation<'a>; 10]>;
|
||||||
|
|
||||||
/// The kind of invalidation we're processing.
|
/// The kind of invalidation we're processing.
|
||||||
///
|
///
|
||||||
|
@ -83,8 +88,8 @@ enum InvalidationKind {
|
||||||
/// An `Invalidation` is a complex selector that describes which elements,
|
/// An `Invalidation` is a complex selector that describes which elements,
|
||||||
/// relative to a current element we are processing, must be restyled.
|
/// relative to a current element we are processing, must be restyled.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Invalidation {
|
pub struct Invalidation<'a> {
|
||||||
selector: Selector<SelectorImpl>,
|
selector: &'a Selector<SelectorImpl>,
|
||||||
/// The offset of the selector pointing to a compound selector.
|
/// The offset of the selector pointing to a compound selector.
|
||||||
///
|
///
|
||||||
/// This order is a "parse order" offset, that is, zero is the leftmost part
|
/// This order is a "parse order" offset, that is, zero is the leftmost part
|
||||||
|
@ -99,9 +104,9 @@ pub struct Invalidation {
|
||||||
matched_by_any_previous: bool,
|
matched_by_any_previous: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Invalidation {
|
impl<'a> Invalidation<'a> {
|
||||||
/// Create a new invalidation for a given selector and offset.
|
/// Create a new invalidation for a given selector and offset.
|
||||||
pub fn new(selector: Selector<SelectorImpl>, offset: usize) -> Self {
|
pub fn new(selector: &'a Selector<SelectorImpl>, offset: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
selector,
|
selector,
|
||||||
offset,
|
offset,
|
||||||
|
@ -112,6 +117,10 @@ impl Invalidation {
|
||||||
/// Whether this invalidation is effective for the next sibling or
|
/// Whether this invalidation is effective for the next sibling or
|
||||||
/// descendant after us.
|
/// descendant after us.
|
||||||
fn effective_for_next(&self) -> bool {
|
fn effective_for_next(&self) -> bool {
|
||||||
|
if self.offset == 0 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(emilio): For pseudo-elements this should be mostly false, except
|
// TODO(emilio): For pseudo-elements this should be mostly false, except
|
||||||
// for the weird pseudos in <input type="number">.
|
// for the weird pseudos in <input type="number">.
|
||||||
//
|
//
|
||||||
|
@ -124,6 +133,10 @@ impl Invalidation {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kind(&self) -> InvalidationKind {
|
fn kind(&self) -> InvalidationKind {
|
||||||
|
if self.offset == 0 {
|
||||||
|
return InvalidationKind::Descendant;
|
||||||
|
}
|
||||||
|
|
||||||
if self.selector.combinator_at_parse_order(self.offset - 1).is_ancestor() {
|
if self.selector.combinator_at_parse_order(self.offset - 1).is_ancestor() {
|
||||||
InvalidationKind::Descendant
|
InvalidationKind::Descendant
|
||||||
} else {
|
} else {
|
||||||
|
@ -132,7 +145,7 @@ impl Invalidation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Invalidation {
|
impl<'a> fmt::Debug for Invalidation<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use cssparser::ToCss;
|
use cssparser::ToCss;
|
||||||
|
|
||||||
|
@ -192,25 +205,23 @@ impl InvalidationResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E, P: 'a> TreeStyleInvalidator<'a, E, P>
|
impl<'a, 'b, E, P: 'a> TreeStyleInvalidator<'a, 'b, E, P>
|
||||||
where
|
where
|
||||||
|
'b: 'a,
|
||||||
E: TElement,
|
E: TElement,
|
||||||
P: InvalidationProcessor<E>,
|
P: InvalidationProcessor<'b, E>,
|
||||||
{
|
{
|
||||||
/// Trivially constructs a new `TreeStyleInvalidator`.
|
/// Trivially constructs a new `TreeStyleInvalidator`.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
element: E,
|
element: E,
|
||||||
quirks_mode: QuirksMode,
|
|
||||||
stack_limit_checker: Option<&'a StackLimitChecker>,
|
stack_limit_checker: Option<&'a StackLimitChecker>,
|
||||||
nth_index_cache: Option<&'a mut NthIndexCache>,
|
|
||||||
processor: &'a mut P,
|
processor: &'a mut P,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
element,
|
element,
|
||||||
quirks_mode,
|
|
||||||
stack_limit_checker,
|
stack_limit_checker,
|
||||||
nth_index_cache,
|
|
||||||
processor,
|
processor,
|
||||||
|
_marker: ::std::marker::PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,21 +229,34 @@ where
|
||||||
pub fn invalidate(mut self) -> InvalidationResult {
|
pub fn invalidate(mut self) -> InvalidationResult {
|
||||||
debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
|
debug!("StyleTreeInvalidator::invalidate({:?})", self.element);
|
||||||
|
|
||||||
|
let mut self_invalidations = InvalidationVector::new();
|
||||||
let mut descendant_invalidations = InvalidationVector::new();
|
let mut descendant_invalidations = InvalidationVector::new();
|
||||||
let mut sibling_invalidations = InvalidationVector::new();
|
let mut sibling_invalidations = InvalidationVector::new();
|
||||||
|
|
||||||
let invalidated_self = self.processor.collect_invalidations(
|
let mut invalidated_self = self.processor.collect_invalidations(
|
||||||
self.element,
|
self.element,
|
||||||
self.nth_index_cache.as_mut().map(|c| &mut **c),
|
&mut self_invalidations,
|
||||||
self.quirks_mode,
|
|
||||||
&mut descendant_invalidations,
|
&mut descendant_invalidations,
|
||||||
&mut sibling_invalidations,
|
&mut sibling_invalidations,
|
||||||
);
|
);
|
||||||
|
|
||||||
debug!("Collected invalidations (self: {}): ", invalidated_self);
|
debug!("Collected invalidations (self: {}): ", invalidated_self);
|
||||||
|
debug!(" > self: {:?}", descendant_invalidations);
|
||||||
debug!(" > descendants: {:?}", descendant_invalidations);
|
debug!(" > descendants: {:?}", descendant_invalidations);
|
||||||
debug!(" > siblings: {:?}", sibling_invalidations);
|
debug!(" > siblings: {:?}", sibling_invalidations);
|
||||||
|
|
||||||
|
let invalidated_self_from_collection = invalidated_self;
|
||||||
|
|
||||||
|
invalidated_self |= self.process_descendant_invalidations(
|
||||||
|
&self_invalidations,
|
||||||
|
&mut descendant_invalidations,
|
||||||
|
&mut sibling_invalidations,
|
||||||
|
);
|
||||||
|
|
||||||
|
if invalidated_self && !invalidated_self_from_collection {
|
||||||
|
self.processor.invalidated_self(self.element);
|
||||||
|
}
|
||||||
|
|
||||||
let invalidated_descendants = self.invalidate_descendants(&descendant_invalidations);
|
let invalidated_descendants = self.invalidate_descendants(&descendant_invalidations);
|
||||||
let invalidated_siblings = self.invalidate_siblings(&mut sibling_invalidations);
|
let invalidated_siblings = self.invalidate_siblings(&mut sibling_invalidations);
|
||||||
|
|
||||||
|
@ -246,7 +270,7 @@ where
|
||||||
/// was invalidated.
|
/// was invalidated.
|
||||||
fn invalidate_siblings(
|
fn invalidate_siblings(
|
||||||
&mut self,
|
&mut self,
|
||||||
sibling_invalidations: &mut InvalidationVector,
|
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if sibling_invalidations.is_empty() {
|
if sibling_invalidations.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -258,19 +282,23 @@ where
|
||||||
while let Some(sibling) = current {
|
while let Some(sibling) = current {
|
||||||
let mut sibling_invalidator = TreeStyleInvalidator::new(
|
let mut sibling_invalidator = TreeStyleInvalidator::new(
|
||||||
sibling,
|
sibling,
|
||||||
self.quirks_mode,
|
|
||||||
self.stack_limit_checker,
|
self.stack_limit_checker,
|
||||||
self.nth_index_cache.as_mut().map(|c| &mut **c),
|
|
||||||
self.processor,
|
self.processor,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut invalidations_for_descendants = InvalidationVector::new();
|
let mut invalidations_for_descendants = InvalidationVector::new();
|
||||||
any_invalidated |=
|
let invalidated_sibling =
|
||||||
sibling_invalidator.process_sibling_invalidations(
|
sibling_invalidator.process_sibling_invalidations(
|
||||||
&mut invalidations_for_descendants,
|
&mut invalidations_for_descendants,
|
||||||
sibling_invalidations,
|
sibling_invalidations,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if invalidated_sibling {
|
||||||
|
sibling_invalidator.processor.invalidated_self(sibling);
|
||||||
|
}
|
||||||
|
|
||||||
|
any_invalidated |= invalidated_sibling;
|
||||||
|
|
||||||
any_invalidated |=
|
any_invalidated |=
|
||||||
sibling_invalidator.invalidate_descendants(
|
sibling_invalidator.invalidate_descendants(
|
||||||
&invalidations_for_descendants
|
&invalidations_for_descendants
|
||||||
|
@ -289,7 +317,7 @@ where
|
||||||
fn invalidate_pseudo_element_or_nac(
|
fn invalidate_pseudo_element_or_nac(
|
||||||
&mut self,
|
&mut self,
|
||||||
child: E,
|
child: E,
|
||||||
invalidations: &InvalidationVector
|
invalidations: &InvalidationVector<'b>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut sibling_invalidations = InvalidationVector::new();
|
let mut sibling_invalidations = InvalidationVector::new();
|
||||||
|
|
||||||
|
@ -314,8 +342,8 @@ where
|
||||||
fn invalidate_child(
|
fn invalidate_child(
|
||||||
&mut self,
|
&mut self,
|
||||||
child: E,
|
child: E,
|
||||||
invalidations: &InvalidationVector,
|
invalidations: &InvalidationVector<'b>,
|
||||||
sibling_invalidations: &mut InvalidationVector,
|
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut invalidations_for_descendants = InvalidationVector::new();
|
let mut invalidations_for_descendants = InvalidationVector::new();
|
||||||
|
|
||||||
|
@ -323,9 +351,7 @@ where
|
||||||
let invalidated_descendants = {
|
let invalidated_descendants = {
|
||||||
let mut child_invalidator = TreeStyleInvalidator::new(
|
let mut child_invalidator = TreeStyleInvalidator::new(
|
||||||
child,
|
child,
|
||||||
self.quirks_mode,
|
|
||||||
self.stack_limit_checker,
|
self.stack_limit_checker,
|
||||||
self.nth_index_cache.as_mut().map(|c| &mut **c),
|
|
||||||
self.processor,
|
self.processor,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -342,6 +368,10 @@ where
|
||||||
sibling_invalidations,
|
sibling_invalidations,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if invalidated_child {
|
||||||
|
child_invalidator.processor.invalidated_self(child);
|
||||||
|
}
|
||||||
|
|
||||||
child_invalidator.invalidate_descendants(&invalidations_for_descendants)
|
child_invalidator.invalidate_descendants(&invalidations_for_descendants)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -359,7 +389,7 @@ where
|
||||||
|
|
||||||
fn invalidate_nac(
|
fn invalidate_nac(
|
||||||
&mut self,
|
&mut self,
|
||||||
invalidations: &InvalidationVector,
|
invalidations: &InvalidationVector<'b>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut any_nac_root = false;
|
let mut any_nac_root = false;
|
||||||
|
|
||||||
|
@ -377,7 +407,7 @@ where
|
||||||
fn invalidate_dom_descendants_of(
|
fn invalidate_dom_descendants_of(
|
||||||
&mut self,
|
&mut self,
|
||||||
parent: E::ConcreteNode,
|
parent: E::ConcreteNode,
|
||||||
invalidations: &InvalidationVector,
|
invalidations: &InvalidationVector<'b>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut any_descendant = false;
|
let mut any_descendant = false;
|
||||||
|
|
||||||
|
@ -411,7 +441,7 @@ where
|
||||||
/// descendants, and invalidate style on them.
|
/// descendants, and invalidate style on them.
|
||||||
fn invalidate_descendants(
|
fn invalidate_descendants(
|
||||||
&mut self,
|
&mut self,
|
||||||
invalidations: &InvalidationVector,
|
invalidations: &InvalidationVector<'b>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if invalidations.is_empty() {
|
if invalidations.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -435,6 +465,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.processor.light_tree_only() {
|
||||||
|
let node = self.element.as_node();
|
||||||
|
return self.invalidate_dom_descendants_of(node, invalidations);
|
||||||
|
}
|
||||||
|
|
||||||
let mut any_descendant = false;
|
let mut any_descendant = false;
|
||||||
|
|
||||||
if let Some(anon_content) = self.element.xbl_binding_anonymous_content() {
|
if let Some(anon_content) = self.element.xbl_binding_anonymous_content() {
|
||||||
|
@ -476,8 +511,8 @@ where
|
||||||
/// Returns whether invalidated the current element's style.
|
/// Returns whether invalidated the current element's style.
|
||||||
fn process_sibling_invalidations(
|
fn process_sibling_invalidations(
|
||||||
&mut self,
|
&mut self,
|
||||||
descendant_invalidations: &mut InvalidationVector,
|
descendant_invalidations: &mut InvalidationVector<'b>,
|
||||||
sibling_invalidations: &mut InvalidationVector,
|
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut new_sibling_invalidations = InvalidationVector::new();
|
let mut new_sibling_invalidations = InvalidationVector::new();
|
||||||
|
@ -511,9 +546,9 @@ where
|
||||||
/// Returns whether our style was invalidated as a result.
|
/// Returns whether our style was invalidated as a result.
|
||||||
fn process_descendant_invalidations(
|
fn process_descendant_invalidations(
|
||||||
&mut self,
|
&mut self,
|
||||||
invalidations: &InvalidationVector,
|
invalidations: &InvalidationVector<'b>,
|
||||||
descendant_invalidations: &mut InvalidationVector,
|
descendant_invalidations: &mut InvalidationVector<'b>,
|
||||||
sibling_invalidations: &mut InvalidationVector,
|
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut invalidated = false;
|
let mut invalidated = false;
|
||||||
|
|
||||||
|
@ -544,30 +579,20 @@ where
|
||||||
/// down in the tree.
|
/// down in the tree.
|
||||||
fn process_invalidation(
|
fn process_invalidation(
|
||||||
&mut self,
|
&mut self,
|
||||||
invalidation: &Invalidation,
|
invalidation: &Invalidation<'b>,
|
||||||
descendant_invalidations: &mut InvalidationVector,
|
descendant_invalidations: &mut InvalidationVector<'b>,
|
||||||
sibling_invalidations: &mut InvalidationVector,
|
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||||
invalidation_kind: InvalidationKind,
|
invalidation_kind: InvalidationKind,
|
||||||
) -> SingleInvalidationResult {
|
) -> SingleInvalidationResult {
|
||||||
debug!("TreeStyleInvalidator::process_invalidation({:?}, {:?}, {:?})",
|
debug!("TreeStyleInvalidator::process_invalidation({:?}, {:?}, {:?})",
|
||||||
self.element, invalidation, invalidation_kind);
|
self.element, invalidation, invalidation_kind);
|
||||||
|
|
||||||
let matching_result = {
|
let matching_result = matches_compound_selector(
|
||||||
let mut context = MatchingContext::new_for_visited(
|
|
||||||
MatchingMode::Normal,
|
|
||||||
None,
|
|
||||||
self.nth_index_cache.as_mut().map(|c| &mut **c),
|
|
||||||
VisitedHandlingMode::AllLinksVisitedAndUnvisited,
|
|
||||||
self.quirks_mode,
|
|
||||||
);
|
|
||||||
|
|
||||||
matches_compound_selector(
|
|
||||||
&invalidation.selector,
|
&invalidation.selector,
|
||||||
invalidation.offset,
|
invalidation.offset,
|
||||||
&mut context,
|
self.processor.matching_context(),
|
||||||
&self.element
|
&self.element
|
||||||
)
|
);
|
||||||
};
|
|
||||||
|
|
||||||
let mut invalidated_self = false;
|
let mut invalidated_self = false;
|
||||||
let mut matched = false;
|
let mut matched = false;
|
||||||
|
@ -628,7 +653,7 @@ where
|
||||||
|
|
||||||
|
|
||||||
let next_invalidation = Invalidation {
|
let next_invalidation = Invalidation {
|
||||||
selector: invalidation.selector.clone(),
|
selector: invalidation.selector,
|
||||||
offset: next_combinator_offset + 1,
|
offset: next_combinator_offset + 1,
|
||||||
matched_by_any_previous: false,
|
matched_by_any_previous: false,
|
||||||
};
|
};
|
||||||
|
@ -719,10 +744,6 @@ where
|
||||||
CompoundSelectorMatchingResult::NotMatched => {}
|
CompoundSelectorMatchingResult::NotMatched => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if invalidated_self {
|
|
||||||
self.processor.invalidated_self(self.element);
|
|
||||||
}
|
|
||||||
|
|
||||||
SingleInvalidationResult { invalidated_self, matched, }
|
SingleInvalidationResult { invalidated_self, matched, }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,9 +306,10 @@ impl<T: SelectorMapEntry> SelectorMap<T> {
|
||||||
/// FIXME(bholley) This overlaps with SelectorMap<Rule>::get_all_matching_rules,
|
/// FIXME(bholley) This overlaps with SelectorMap<Rule>::get_all_matching_rules,
|
||||||
/// but that function is extremely hot and I'd rather not rearrange it.
|
/// but that function is extremely hot and I'd rather not rearrange it.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn lookup<E, F>(&self, element: E, quirks_mode: QuirksMode, f: &mut F) -> bool
|
pub fn lookup<'a, E, F>(&'a self, element: E, quirks_mode: QuirksMode, f: &mut F) -> bool
|
||||||
where E: TElement,
|
where
|
||||||
F: FnMut(&T) -> bool
|
E: TElement,
|
||||||
|
F: FnMut(&'a T) -> bool
|
||||||
{
|
{
|
||||||
// Id.
|
// Id.
|
||||||
if let Some(id) = element.get_id() {
|
if let Some(id) = element.get_id() {
|
||||||
|
@ -366,15 +367,17 @@ impl<T: SelectorMapEntry> SelectorMap<T> {
|
||||||
///
|
///
|
||||||
/// Returns false if the callback ever returns false.
|
/// Returns false if the callback ever returns false.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn lookup_with_additional<E, F>(&self,
|
pub fn lookup_with_additional<'a, E, F>(
|
||||||
|
&'a self,
|
||||||
element: E,
|
element: E,
|
||||||
quirks_mode: QuirksMode,
|
quirks_mode: QuirksMode,
|
||||||
additional_id: Option<&Atom>,
|
additional_id: Option<&Atom>,
|
||||||
additional_classes: &[Atom],
|
additional_classes: &[Atom],
|
||||||
f: &mut F)
|
f: &mut F,
|
||||||
-> bool
|
) -> bool
|
||||||
where E: TElement,
|
where
|
||||||
F: FnMut(&T) -> bool
|
E: TElement,
|
||||||
|
F: FnMut(&'a T) -> bool
|
||||||
{
|
{
|
||||||
// Do the normal lookup.
|
// Do the normal lookup.
|
||||||
if !self.lookup(element, quirks_mode, f) {
|
if !self.lookup(element, quirks_mode, f) {
|
||||||
|
|
|
@ -484,11 +484,12 @@ impl Stylist {
|
||||||
/// NOTE(heycam) This might be better as an `iter_invalidation_maps`, once
|
/// NOTE(heycam) This might be better as an `iter_invalidation_maps`, once
|
||||||
/// we have `impl trait` and can return that easily without bothering to
|
/// we have `impl trait` and can return that easily without bothering to
|
||||||
/// create a whole new iterator type.
|
/// create a whole new iterator type.
|
||||||
pub fn each_invalidation_map<F>(&self, mut f: F)
|
pub fn each_invalidation_map<'a, F>(&'a self, mut f: F)
|
||||||
where F: FnMut(&InvalidationMap)
|
where
|
||||||
|
F: FnMut(&'a InvalidationMap, Origin)
|
||||||
{
|
{
|
||||||
for (data, _) in self.cascade_data.iter_origins() {
|
for (data, origin) in self.cascade_data.iter_origins() {
|
||||||
f(&data.invalidation_map)
|
f(&data.invalidation_map, origin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,9 @@ use style::gecko::global_style_data::{GLOBAL_STYLE_DATA, GlobalStyleData, STYLE_
|
||||||
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
||||||
use style::gecko::selector_parser::PseudoElement;
|
use style::gecko::selector_parser::PseudoElement;
|
||||||
use style::gecko::traversal::RecalcStyleOnly;
|
use style::gecko::traversal::RecalcStyleOnly;
|
||||||
use style::gecko::wrapper::GeckoElement;
|
use style::gecko::wrapper::{GeckoElement, GeckoNode};
|
||||||
use style::gecko_bindings::bindings;
|
use style::gecko_bindings::bindings;
|
||||||
use style::gecko_bindings::bindings::{RawGeckoElementBorrowed, RawGeckoElementBorrowedOrNull};
|
use style::gecko_bindings::bindings::{RawGeckoElementBorrowed, RawGeckoElementBorrowedOrNull, RawGeckoNodeBorrowed};
|
||||||
use style::gecko_bindings::bindings::{RawGeckoKeyframeListBorrowed, RawGeckoKeyframeListBorrowedMut};
|
use style::gecko_bindings::bindings::{RawGeckoKeyframeListBorrowed, RawGeckoKeyframeListBorrowedMut};
|
||||||
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
|
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
|
||||||
use style::gecko_bindings::bindings::{RawServoDocumentRule, RawServoDocumentRuleBorrowed};
|
use style::gecko_bindings::bindings::{RawServoDocumentRule, RawServoDocumentRuleBorrowed};
|
||||||
|
@ -1614,6 +1614,59 @@ pub unsafe extern "C" fn Servo_SelectorList_Matches(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Servo_SelectorList_QueryFirst(
|
||||||
|
node: RawGeckoNodeBorrowed,
|
||||||
|
selectors: RawServoSelectorListBorrowed,
|
||||||
|
) -> *const structs::RawGeckoElement {
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
use style::dom_apis::{self, QueryFirst};
|
||||||
|
|
||||||
|
let node = GeckoNode(node);
|
||||||
|
let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
|
||||||
|
let mut result = None;
|
||||||
|
dom_apis::query_selector::<GeckoElement, QueryFirst>(
|
||||||
|
node,
|
||||||
|
&selectors,
|
||||||
|
&mut result,
|
||||||
|
node.owner_document_quirks_mode(),
|
||||||
|
);
|
||||||
|
|
||||||
|
result.map_or(ptr::null(), |e| e.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Servo_SelectorList_QueryAll(
|
||||||
|
node: RawGeckoNodeBorrowed,
|
||||||
|
selectors: RawServoSelectorListBorrowed,
|
||||||
|
content_list: *mut structs::nsSimpleContentList,
|
||||||
|
) {
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
use style::dom_apis::{self, QueryAll};
|
||||||
|
|
||||||
|
let node = GeckoNode(node);
|
||||||
|
let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
|
||||||
|
let mut result = SmallVec::new();
|
||||||
|
|
||||||
|
dom_apis::query_selector::<GeckoElement, QueryAll>(
|
||||||
|
node,
|
||||||
|
&selectors,
|
||||||
|
&mut result,
|
||||||
|
node.owner_document_quirks_mode(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if !result.is_empty() {
|
||||||
|
// NOTE(emilio): This relies on a slice of GeckoElement having the same
|
||||||
|
// memory representation than a slice of element pointers.
|
||||||
|
bindings::Gecko_ContentList_AppendAll(
|
||||||
|
content_list,
|
||||||
|
result.as_ptr() as *mut *const _,
|
||||||
|
result.len(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_ImportRule_GetHref(rule: RawServoImportRuleBorrowed, result: *mut nsAString) {
|
pub extern "C" fn Servo_ImportRule_GetHref(rule: RawServoImportRuleBorrowed, result: *mut nsAString) {
|
||||||
read_locked_arc(rule, |rule: &ImportRule| {
|
read_locked_arc(rule, |rule: &ImportRule| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue