зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset dbd300f4d75b for build bustage. r=backout on a CLOSED TREE
This commit is contained in:
Родитель
eebc5b65c0
Коммит
855fb4576a
|
@ -213,10 +213,6 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
|
|||
unsafe { self.node.get_flag(NodeFlags::CAN_BE_FRAGMENTED) }
|
||||
}
|
||||
|
||||
fn is_in_document(&self) -> bool {
|
||||
unsafe { self.node.get_flag(NodeFlags::IS_IN_DOC) }
|
||||
}
|
||||
|
||||
unsafe fn set_can_be_fragmented(&self, value: bool) {
|
||||
self.node.set_flag(NodeFlags::CAN_BE_FRAGMENTED, value)
|
||||
}
|
||||
|
@ -421,7 +417,7 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
|||
}
|
||||
|
||||
unsafe fn set_dirty_descendants(&self) {
|
||||
debug_assert!(self.as_node().is_in_document());
|
||||
debug_assert!(self.as_node().node.get_flag(NodeFlags::IS_IN_DOC));
|
||||
self.as_node().node.set_flag(NodeFlags::HAS_DIRTY_DESCENDANTS, true)
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,6 @@ struct LocalMatchingContext<'a, 'b: 'a, Impl: SelectorImpl> {
|
|||
matches_hover_and_active_quirk: bool,
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn matches_selector_list<E>(
|
||||
selector_list: &SelectorList<E::Impl>,
|
||||
element: &E,
|
||||
|
@ -374,7 +373,6 @@ where
|
|||
}
|
||||
|
||||
/// Matches a complex selector.
|
||||
#[inline(always)]
|
||||
pub fn matches_complex_selector<E, F>(
|
||||
mut iter: SelectorIter<E::Impl>,
|
||||
element: &E,
|
||||
|
@ -387,8 +385,8 @@ where
|
|||
{
|
||||
// If this is the special pseudo-element mode, consume the ::pseudo-element
|
||||
// before proceeding, since the caller has already handled that part.
|
||||
if context.matching_mode == MatchingMode::ForStatelessPseudoElement &&
|
||||
context.nesting_level == 0 {
|
||||
if context.nesting_level == 0 &&
|
||||
context.matching_mode == MatchingMode::ForStatelessPseudoElement {
|
||||
// Consume the pseudo.
|
||||
match *iter.next().unwrap() {
|
||||
Component::PseudoElement(ref pseudo) => {
|
||||
|
@ -573,12 +571,12 @@ where
|
|||
// Only ancestor combinators are allowed while looking for
|
||||
// relevant links, so switch to not looking.
|
||||
*relevant_link = RelevantLinkStatus::NotLooking;
|
||||
SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant
|
||||
SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant
|
||||
}
|
||||
Combinator::Child |
|
||||
Combinator::Descendant |
|
||||
Combinator::PseudoElement => {
|
||||
SelectorMatchingResult::NotMatchedGlobally
|
||||
SelectorMatchingResult::NotMatchedGlobally
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -122,7 +122,6 @@ where
|
|||
{
|
||||
type Item = N;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<N> {
|
||||
let prev = match self.previous.take() {
|
||||
None => return None,
|
||||
|
@ -147,18 +146,6 @@ pub trait TDocument : Sized + Copy + Clone {
|
|||
|
||||
/// Returns the quirks mode of this document.
|
||||
fn quirks_mode(&self) -> QuirksMode;
|
||||
|
||||
/// Get a list of elements with a given ID in this document, sorted by
|
||||
/// document position.
|
||||
///
|
||||
/// Can return an error to signal that this list is not available, or also
|
||||
/// return an empty slice.
|
||||
fn elements_with_id(
|
||||
&self,
|
||||
_id: &Atom,
|
||||
) -> Result<&[<Self::ConcreteNode as TNode>::ConcreteElement], ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
/// The `TNode` trait. This is the main generic trait over which the style
|
||||
|
@ -193,9 +180,6 @@ pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo + PartialEq {
|
|||
DomChildren(self.first_child())
|
||||
}
|
||||
|
||||
/// Returns whether the node is attached to a document.
|
||||
fn is_in_document(&self) -> bool;
|
||||
|
||||
/// Iterate over the DOM children of a node, in preorder.
|
||||
fn dom_descendants(&self) -> DomDescendants<Self> {
|
||||
DomDescendants {
|
||||
|
@ -206,7 +190,6 @@ pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo + PartialEq {
|
|||
|
||||
/// Returns the next children in pre-order, optionally scoped to a subtree
|
||||
/// root.
|
||||
#[inline]
|
||||
fn next_in_preorder(&self, scoped_to: Option<Self>) -> Option<Self> {
|
||||
if let Some(c) = self.first_child() {
|
||||
return Some(c);
|
||||
|
|
|
@ -5,16 +5,12 @@
|
|||
//! Generic implementations of some DOM APIs so they can be shared between Servo
|
||||
//! and Gecko.
|
||||
|
||||
use Atom;
|
||||
use context::QuirksMode;
|
||||
use dom::{TDocument, TElement, TNode};
|
||||
use invalidation::element::invalidator::{Invalidation, InvalidationProcessor, InvalidationVector};
|
||||
use selectors::{Element, NthIndexCache, SelectorList};
|
||||
use selectors::attr::CaseSensitivity;
|
||||
use selectors::matching::{self, MatchingContext, MatchingMode};
|
||||
use selectors::parser::{Combinator, Component, LocalName};
|
||||
use smallvec::SmallVec;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#dom-element-matches>
|
||||
pub fn element_matches<E>(
|
||||
|
@ -222,103 +218,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns whether a given element is descendant of a given `root` node.
|
||||
/// Fast paths for a given selector query.
|
||||
///
|
||||
/// NOTE(emilio): if root == element, this returns false.
|
||||
fn element_is_descendant_of<E>(element: E, root: E::ConcreteNode) -> bool
|
||||
where
|
||||
E: TElement,
|
||||
{
|
||||
if element.as_node().is_in_document() && root == root.owner_doc().as_node() {
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut current = element.as_node().parent_node();
|
||||
while let Some(n) = current.take() {
|
||||
if n == root {
|
||||
return true;
|
||||
}
|
||||
|
||||
current = n.parent_node();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Fast path for iterating over every element with a given id in the document
|
||||
/// that `root` is connected to.
|
||||
fn fast_connected_elements_with_id<'a, D>(
|
||||
doc: &'a D,
|
||||
root: D::ConcreteNode,
|
||||
id: &Atom,
|
||||
quirks_mode: QuirksMode,
|
||||
) -> Result<&'a [<D::ConcreteNode as TNode>::ConcreteElement], ()>
|
||||
where
|
||||
D: TDocument,
|
||||
{
|
||||
debug_assert_eq!(root.owner_doc().as_node(), doc.as_node());
|
||||
|
||||
let case_sensitivity = quirks_mode.classes_and_ids_case_sensitivity();
|
||||
if case_sensitivity != CaseSensitivity::CaseSensitive {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
if !root.is_in_document() {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
doc.elements_with_id(id)
|
||||
}
|
||||
|
||||
/// Collects elements with a given id under `root`, that pass `filter`.
|
||||
fn collect_elements_with_id<E, Q, F>(
|
||||
/// 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,
|
||||
id: &Atom,
|
||||
results: &mut Q::Output,
|
||||
quirks_mode: QuirksMode,
|
||||
mut filter: F,
|
||||
)
|
||||
where
|
||||
E: TElement,
|
||||
Q: SelectorQuery<E>,
|
||||
F: FnMut(E) -> bool,
|
||||
{
|
||||
let doc = root.owner_doc();
|
||||
let elements = match fast_connected_elements_with_id(&doc, root, id, quirks_mode) {
|
||||
Ok(elements) => elements,
|
||||
Err(()) => {
|
||||
let case_sensitivity =
|
||||
quirks_mode.classes_and_ids_case_sensitivity();
|
||||
|
||||
collect_all_elements::<E, Q, _>(root, results, |e| {
|
||||
e.has_id(id, case_sensitivity) && filter(e)
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
for element in elements {
|
||||
// If the element is not an actual descendant of the root, even though
|
||||
// it's connected, we don't really care about it.
|
||||
if !element_is_descendant_of(*element, root) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !filter(*element) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Q::append_element(results, *element);
|
||||
if Q::should_stop_after_first_match() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fast paths for querySelector with a single simple selector.
|
||||
fn query_selector_single_query<E, Q>(
|
||||
root: E::ConcreteNode,
|
||||
component: &Component<E::Impl>,
|
||||
selector_list: &SelectorList<E::Impl>,
|
||||
results: &mut Q::Output,
|
||||
quirks_mode: QuirksMode,
|
||||
) -> Result<(), ()>
|
||||
|
@ -326,18 +232,36 @@ 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) => {
|
||||
collect_elements_with_id::<E, Q, _>(
|
||||
root,
|
||||
id,
|
||||
results,
|
||||
quirks_mode,
|
||||
|_| true,
|
||||
);
|
||||
// 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();
|
||||
|
@ -363,139 +287,6 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// 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,
|
||||
matching_context: &mut MatchingContext<E::Impl>,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
E: TElement,
|
||||
Q: SelectorQuery<E>,
|
||||
{
|
||||
// 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 quirks_mode = matching_context.quirks_mode();
|
||||
|
||||
// Let's just care about the easy cases for now.
|
||||
if selector.len() == 1 {
|
||||
return query_selector_single_query::<E, Q>(
|
||||
root,
|
||||
selector.iter().next().unwrap(),
|
||||
results,
|
||||
quirks_mode,
|
||||
);
|
||||
}
|
||||
|
||||
let mut iter = selector.iter();
|
||||
let mut combinator: Option<Combinator> = None;
|
||||
|
||||
loop {
|
||||
debug_assert!(combinator.map_or(true, |c| !c.is_sibling()));
|
||||
|
||||
'component_loop: for component in &mut iter {
|
||||
match *component {
|
||||
Component::ID(ref id) => {
|
||||
if combinator.is_none() {
|
||||
// In the rightmost compound, just find descendants of
|
||||
// root that match the selector list with that id.
|
||||
collect_elements_with_id::<E, Q, _>(
|
||||
root,
|
||||
id,
|
||||
results,
|
||||
quirks_mode,
|
||||
|e| {
|
||||
matching::matches_selector_list(
|
||||
selector_list,
|
||||
&e,
|
||||
matching_context,
|
||||
)
|
||||
}
|
||||
);
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let doc = root.owner_doc();
|
||||
let elements =
|
||||
fast_connected_elements_with_id(&doc, root, id, quirks_mode)?;
|
||||
|
||||
if elements.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Results need to be in document order. Let's not bother
|
||||
// reordering or deduplicating nodes, which we would need to
|
||||
// do if one element with the given id were a descendant of
|
||||
// another element with that given id.
|
||||
if !Q::should_stop_after_first_match() && elements.len() > 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
for element in elements {
|
||||
// If the element is not a descendant of the root, then
|
||||
// it may have descendants that match our selector that
|
||||
// _are_ descendants of the root, and other descendants
|
||||
// that match our selector that are _not_.
|
||||
//
|
||||
// So we can't just walk over the element's descendants
|
||||
// and match the selector against all of them, nor can
|
||||
// we skip looking at this element's descendants.
|
||||
//
|
||||
// Give up on trying to optimize based on this id and
|
||||
// keep walking our selector.
|
||||
if !element_is_descendant_of(*element, root) {
|
||||
continue 'component_loop;
|
||||
}
|
||||
|
||||
query_selector_slow::<E, Q>(
|
||||
element.as_node(),
|
||||
selector_list,
|
||||
results,
|
||||
matching_context,
|
||||
);
|
||||
|
||||
if Q::should_stop_after_first_match() && !Q::is_empty(&results) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
let next_combinator = match iter.next_sequence() {
|
||||
None => return Err(()),
|
||||
Some(c) => c,
|
||||
};
|
||||
|
||||
// We don't want to scan stuff affected by sibling combinators,
|
||||
// given we scan the subtree of elements with a given id (and we
|
||||
// don't want to care about scanning the siblings' subtrees).
|
||||
if next_combinator.is_sibling() {
|
||||
// Advance to the next combinator.
|
||||
for _ in &mut iter {}
|
||||
continue;
|
||||
}
|
||||
|
||||
combinator = Some(next_combinator);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Slow path for a given selector query.
|
||||
fn query_selector_slow<E, Q>(
|
||||
root: E::ConcreteNode,
|
||||
|
@ -512,21 +303,11 @@ where
|
|||
});
|
||||
}
|
||||
|
||||
/// Whether the invalidation machinery should be used for this query.
|
||||
#[derive(PartialEq)]
|
||||
pub enum MayUseInvalidation {
|
||||
/// We may use it if we deem it useful.
|
||||
Yes,
|
||||
/// Don't use it.
|
||||
No,
|
||||
}
|
||||
|
||||
/// <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,
|
||||
may_use_invalidation: MayUseInvalidation,
|
||||
)
|
||||
where
|
||||
E: TElement,
|
||||
|
@ -535,7 +316,21 @@ where
|
|||
use invalidation::element::invalidator::TreeStyleInvalidator;
|
||||
|
||||
let quirks_mode = root.owner_doc().quirks_mode();
|
||||
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,
|
||||
|
@ -547,32 +342,12 @@ where
|
|||
let root_element = root.as_element();
|
||||
matching_context.scope_element = root_element.map(|e| e.opaque());
|
||||
|
||||
let fast_result = query_selector_fast::<E, Q>(
|
||||
root,
|
||||
selector_list,
|
||||
results,
|
||||
&mut matching_context,
|
||||
);
|
||||
|
||||
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.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// A selector with a combinator needs to have a length of at least 3: A
|
||||
// simple selector, a combinator, and another simple selector.
|
||||
let invalidation_may_be_useful =
|
||||
may_use_invalidation == MayUseInvalidation::Yes &&
|
||||
selector_list.0.iter().any(|s| s.len() > 2);
|
||||
selector_list.0.iter().any(|s| s.len() > 1);
|
||||
|
||||
if root_element.is_some() || !invalidation_may_be_useful {
|
||||
query_selector_slow::<E, Q>(
|
||||
|
|
|
@ -30,7 +30,6 @@ use gecko_bindings::structs::RawGeckoComputedTiming;
|
|||
use gecko_bindings::structs::RawGeckoCSSPropertyIDList;
|
||||
use gecko_bindings::structs::RawGeckoDocument;
|
||||
use gecko_bindings::structs::RawGeckoElement;
|
||||
use gecko_bindings::structs::Element;
|
||||
use gecko_bindings::structs::RawGeckoKeyframeList;
|
||||
use gecko_bindings::structs::RawGeckoPropertyValuePairList;
|
||||
use gecko_bindings::structs::RawGeckoComputedKeyframeValuesList;
|
||||
|
@ -1211,9 +1210,9 @@ extern "C" {
|
|||
} extern "C" {
|
||||
pub fn Servo_SelectorList_Closest ( arg1 : RawGeckoElementBorrowed , arg2 : RawServoSelectorListBorrowed , ) -> * const RawGeckoElement ;
|
||||
} extern "C" {
|
||||
pub fn Servo_SelectorList_QueryFirst ( arg1 : RawGeckoNodeBorrowed , arg2 : RawServoSelectorListBorrowed , may_use_invalidation : bool , ) -> * const RawGeckoElement ;
|
||||
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 , may_use_invalidation : bool , ) ;
|
||||
pub fn Servo_SelectorList_QueryAll ( arg1 : RawGeckoNodeBorrowed , arg2 : RawServoSelectorListBorrowed , content_list : * mut nsSimpleContentList , ) ;
|
||||
} extern "C" {
|
||||
pub fn Servo_StyleSet_AddSizeOfExcludingThis ( malloc_size_of : MallocSizeOf , malloc_enclosing_size_of : MallocSizeOf , sizes : * mut ServoStyleSetSizes , set : RawServoStyleSetBorrowed , ) ;
|
||||
} extern "C" {
|
||||
|
@ -1226,8 +1225,6 @@ extern "C" {
|
|||
pub fn Servo_StyleSet_MightHaveAttributeDependency ( set : RawServoStyleSetBorrowed , element : RawGeckoElementBorrowed , local_name : * mut nsAtom , ) -> bool ;
|
||||
} extern "C" {
|
||||
pub fn Servo_StyleSet_HasStateDependency ( set : RawServoStyleSetBorrowed , element : RawGeckoElementBorrowed , state : u64 , ) -> bool ;
|
||||
} extern "C" {
|
||||
pub fn Servo_StyleSet_HasDocumentStateDependency ( set : RawServoStyleSetBorrowed , state : u64 , ) -> bool ;
|
||||
} extern "C" {
|
||||
pub fn Servo_CssRules_ListTypes ( rules : ServoCssRulesBorrowed , result : nsTArrayBorrowed_uintptr_t , ) ;
|
||||
} extern "C" {
|
||||
|
@ -1576,6 +1573,4 @@ extern "C" {
|
|||
pub fn Gecko_ReportUnexpectedCSSError ( reporter : * mut ErrorReporter , message : * const :: std :: os :: raw :: c_char , param : * const :: std :: os :: raw :: c_char , paramLen : u32 , prefix : * const :: std :: os :: raw :: c_char , prefixParam : * const :: std :: os :: raw :: c_char , prefixParamLen : u32 , suffix : * const :: std :: os :: raw :: c_char , source : * const :: std :: os :: raw :: c_char , sourceLen : u32 , lineNumber : u32 , colNumber : u32 , ) ;
|
||||
} extern "C" {
|
||||
pub fn Gecko_ContentList_AppendAll ( aContentList : * mut nsSimpleContentList , aElements : * mut * const RawGeckoElement , aLength : usize , ) ;
|
||||
} extern "C" {
|
||||
pub fn Gecko_GetElementsWithId ( aDocument : * const nsIDocument , aId : * mut nsAtom , ) -> * const nsTArray < * mut Element > ;
|
||||
}
|
|
@ -110,26 +110,6 @@ impl<'ld> TDocument for GeckoDocument<'ld> {
|
|||
fn quirks_mode(&self) -> QuirksMode {
|
||||
self.0.mCompatMode.into()
|
||||
}
|
||||
|
||||
fn elements_with_id(&self, id: &Atom) -> Result<&[GeckoElement<'ld>], ()> {
|
||||
unsafe {
|
||||
let array = bindings::Gecko_GetElementsWithId(self.0, id.as_ptr());
|
||||
if array.is_null() {
|
||||
return Ok(&[]);
|
||||
}
|
||||
|
||||
let elements: &[*mut RawGeckoElement] = &**array;
|
||||
|
||||
// NOTE(emilio): We rely on the in-memory representation of
|
||||
// GeckoElement<'ld> and *mut RawGeckoElement being the same.
|
||||
#[allow(dead_code)]
|
||||
unsafe fn static_assert() {
|
||||
mem::transmute::<*mut RawGeckoElement, GeckoElement<'static>>(0xbadc0de as *mut _);
|
||||
}
|
||||
|
||||
Ok(mem::transmute(elements))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple wrapper over a non-null Gecko node (`nsINode`) pointer.
|
||||
|
@ -262,7 +242,6 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
type ConcreteDocument = GeckoDocument<'ln>;
|
||||
type ConcreteElement = GeckoElement<'ln>;
|
||||
|
||||
#[inline]
|
||||
fn parent_node(&self) -> Option<Self> {
|
||||
unsafe { self.0.mParent.as_ref().map(GeckoNode) }
|
||||
}
|
||||
|
@ -293,11 +272,6 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
GeckoDocument(unsafe { &*self.node_info().mDocument })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_in_document(&self) -> bool {
|
||||
self.get_bool_flag(nsINode_BooleanFlag::IsInDocument)
|
||||
}
|
||||
|
||||
fn traversal_parent(&self) -> Option<GeckoElement<'ln>> {
|
||||
self.flattened_tree_parent().and_then(|n| n.as_element())
|
||||
}
|
||||
|
@ -1768,12 +1742,10 @@ impl<'le> Hash for GeckoElement<'le> {
|
|||
impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||
type Impl = SelectorImpl;
|
||||
|
||||
#[inline]
|
||||
fn opaque(&self) -> OpaqueElement {
|
||||
OpaqueElement::new(self.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parent_element(&self) -> Option<Self> {
|
||||
// FIXME(emilio): This will need to jump across if the parent node is a
|
||||
// shadow root to get the shadow host.
|
||||
|
@ -1786,7 +1758,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
self.closest_non_native_anonymous_ancestor()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn first_child_element(&self) -> Option<Self> {
|
||||
let mut child = self.as_node().first_child();
|
||||
while let Some(child_node) = child {
|
||||
|
@ -1798,7 +1769,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last_child_element(&self) -> Option<Self> {
|
||||
let mut child = self.as_node().last_child();
|
||||
while let Some(child_node) = child {
|
||||
|
@ -1810,7 +1780,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn prev_sibling_element(&self) -> Option<Self> {
|
||||
let mut sibling = self.as_node().prev_sibling();
|
||||
while let Some(sibling_node) = sibling {
|
||||
|
@ -1822,7 +1791,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next_sibling_element(&self) -> Option<Self> {
|
||||
let mut sibling = self.as_node().next_sibling();
|
||||
while let Some(sibling_node) = sibling {
|
||||
|
@ -1914,14 +1882,12 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_local_name(&self) -> &WeakAtom {
|
||||
unsafe {
|
||||
WeakAtom::new(self.as_node().node_info().mInner.mName)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_namespace(&self) -> &WeakNamespace {
|
||||
unsafe {
|
||||
WeakNamespace::new(Gecko_Namespace(self.0))
|
||||
|
@ -2088,7 +2054,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
self.get_state().intersects(NonTSPseudoClass::AnyLink.state_flag())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_id(&self, id: &Atom, case_sensitivity: CaseSensitivity) -> bool {
|
||||
if !self.has_id() {
|
||||
return false
|
||||
|
@ -2105,7 +2070,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn has_class(&self, name: &Atom, case_sensitivity: CaseSensitivity) -> bool {
|
||||
if !self.may_have_class() {
|
||||
return false;
|
||||
|
@ -2117,18 +2081,15 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
Gecko_ClassOrClassList)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_html_element_in_html_document(&self) -> bool {
|
||||
self.is_html_element() &&
|
||||
self.as_node().owner_doc().is_html_document()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ignores_nth_child_selectors(&self) -> bool {
|
||||
self.is_root_of_anonymous_subtree()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn blocks_ancestor_combinators(&self) -> bool {
|
||||
if !self.is_root_of_anonymous_subtree() {
|
||||
return false
|
||||
|
|
|
@ -317,7 +317,7 @@ where
|
|||
fn invalidate_pseudo_element_or_nac(
|
||||
&mut self,
|
||||
child: E,
|
||||
invalidations: &[Invalidation<'b>],
|
||||
invalidations: &InvalidationVector<'b>,
|
||||
) -> bool {
|
||||
let mut sibling_invalidations = InvalidationVector::new();
|
||||
|
||||
|
@ -342,7 +342,7 @@ where
|
|||
fn invalidate_child(
|
||||
&mut self,
|
||||
child: E,
|
||||
invalidations: &[Invalidation<'b>],
|
||||
invalidations: &InvalidationVector<'b>,
|
||||
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||
) -> bool {
|
||||
let mut invalidations_for_descendants = InvalidationVector::new();
|
||||
|
@ -389,7 +389,7 @@ where
|
|||
|
||||
fn invalidate_nac(
|
||||
&mut self,
|
||||
invalidations: &[Invalidation<'b>],
|
||||
invalidations: &InvalidationVector<'b>,
|
||||
) -> bool {
|
||||
let mut any_nac_root = false;
|
||||
|
||||
|
@ -407,7 +407,7 @@ where
|
|||
fn invalidate_dom_descendants_of(
|
||||
&mut self,
|
||||
parent: E::ConcreteNode,
|
||||
invalidations: &[Invalidation<'b>],
|
||||
invalidations: &InvalidationVector<'b>,
|
||||
) -> bool {
|
||||
let mut any_descendant = false;
|
||||
|
||||
|
@ -441,7 +441,7 @@ where
|
|||
/// descendants, and invalidate style on them.
|
||||
fn invalidate_descendants(
|
||||
&mut self,
|
||||
invalidations: &[Invalidation<'b>],
|
||||
invalidations: &InvalidationVector<'b>,
|
||||
) -> bool {
|
||||
if invalidations.is_empty() {
|
||||
return false;
|
||||
|
@ -546,7 +546,7 @@ where
|
|||
/// Returns whether our style was invalidated as a result.
|
||||
fn process_descendant_invalidations(
|
||||
&mut self,
|
||||
invalidations: &[Invalidation<'b>],
|
||||
invalidations: &InvalidationVector<'b>,
|
||||
descendant_invalidations: &mut InvalidationVector<'b>,
|
||||
sibling_invalidations: &mut InvalidationVector<'b>,
|
||||
) -> bool {
|
||||
|
|
|
@ -1693,27 +1693,17 @@ pub unsafe extern "C" fn Servo_SelectorList_Matches(
|
|||
pub unsafe extern "C" fn Servo_SelectorList_QueryFirst(
|
||||
node: RawGeckoNodeBorrowed,
|
||||
selectors: RawServoSelectorListBorrowed,
|
||||
may_use_invalidation: bool,
|
||||
) -> *const structs::RawGeckoElement {
|
||||
use std::borrow::Borrow;
|
||||
use style::dom_apis::{self, MayUseInvalidation, QueryFirst};
|
||||
use style::dom_apis::{self, QueryFirst};
|
||||
|
||||
let node = GeckoNode(node);
|
||||
let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
|
||||
let mut result = None;
|
||||
|
||||
let may_use_invalidation =
|
||||
if may_use_invalidation {
|
||||
MayUseInvalidation::Yes
|
||||
} else {
|
||||
MayUseInvalidation::No
|
||||
};
|
||||
|
||||
dom_apis::query_selector::<GeckoElement, QueryFirst>(
|
||||
node,
|
||||
&selectors,
|
||||
&mut result,
|
||||
may_use_invalidation,
|
||||
);
|
||||
|
||||
result.map_or(ptr::null(), |e| e.0)
|
||||
|
@ -1724,28 +1714,19 @@ pub unsafe extern "C" fn Servo_SelectorList_QueryAll(
|
|||
node: RawGeckoNodeBorrowed,
|
||||
selectors: RawServoSelectorListBorrowed,
|
||||
content_list: *mut structs::nsSimpleContentList,
|
||||
may_use_invalidation: bool,
|
||||
) {
|
||||
use smallvec::SmallVec;
|
||||
use std::borrow::Borrow;
|
||||
use style::dom_apis::{self, MayUseInvalidation, QueryAll};
|
||||
use style::dom_apis::{self, QueryAll};
|
||||
|
||||
let node = GeckoNode(node);
|
||||
let selectors = ::selectors::SelectorList::from_ffi(selectors).borrow();
|
||||
let mut result = SmallVec::new();
|
||||
|
||||
let may_use_invalidation =
|
||||
if may_use_invalidation {
|
||||
MayUseInvalidation::Yes
|
||||
} else {
|
||||
MayUseInvalidation::No
|
||||
};
|
||||
|
||||
dom_apis::query_selector::<GeckoElement, QueryAll>(
|
||||
node,
|
||||
&selectors,
|
||||
&mut result,
|
||||
may_use_invalidation,
|
||||
);
|
||||
|
||||
if !result.is_empty() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче