/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
//! Data needed to style a Gecko document.
usecrate::dom::TElement; usecrate::gecko_bindings::bindings; usecrate::gecko_bindings::structs::{ self, ServoStyleSetSizes, StyleSheet as DomStyleSheet, StyleSheetInfo,
}; usecrate::invalidation::media_queries::{MediaListKey, ToMediaListKey}; usecrate::media_queries::{Device, MediaList}; usecrate::properties::ComputedValues; usecrate::selector_parser::SnapshotMap; usecrate::shared_lock::{SharedRwLockReadGuard, StylesheetGuards}; usecrate::stylesheets::scope_rule::ImplicitScopeRoot; usecrate::stylesheets::{StylesheetContents, StylesheetInDocument}; usecrate::stylist::Stylist; use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use malloc_size_of::MallocSizeOfOps; use selectors::Element; use servo_arc::Arc; use std::fmt;
usesuper::wrapper::GeckoElement;
/// Little wrapper to a Gecko style sheet. #[derive(Eq, PartialEq)] pubstruct GeckoStyleSheet(*const DomStyleSheet);
// NOTE(emilio): These are kind of a lie. We allow to make these Send + Sync so that other data // structures can also be Send and Sync, but Gecko's stylesheets are main-thread-reference-counted. // // We assert that we reference-count in the right thread (in the Addref/Release implementations). // Sending these to a different thread can't really happen (it could theoretically really happen if // we allowed @import rules inside a nested style rule, but that can't happen per spec and would be // a parser bug, caught by the asserts). unsafeimpl Send for GeckoStyleSheet {} unsafeimpl Sync for GeckoStyleSheet {}
impl GeckoStyleSheet { /// Create a `GeckoStyleSheet` from a raw `DomStyleSheet` pointer. #[inline] pubunsafefn new(s: *const DomStyleSheet) -> Self {
debug_assert!(!s.is_null());
bindings::Gecko_StyleSheet_AddRef(s); Self::from_addrefed(s)
}
/// Create a `GeckoStyleSheet` from a raw `DomStyleSheet` pointer that /// already holds a strong reference. #[inline] pubunsafefn from_addrefed(s: *const DomStyleSheet) -> Self {
assert!(!s.is_null());
GeckoStyleSheet(s)
}
/// HACK(emilio): This is so that we can avoid crashing release due to /// bug 1719963 and can hopefully get a useful report from fuzzers. #[inline] pubfn hack_is_null(&self) -> bool { self.0.is_null()
}
/// Get the raw `StyleSheet` that we're wrapping. pubfn raw(&self) -> &DomStyleSheet { unsafe { &*self.0 }
}
impl StylesheetInDocument for GeckoStyleSheet { fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> { usecrate::gecko_bindings::structs::mozilla::dom::MediaList as DomMediaList; unsafe { let dom_media_list = self.raw().mMedia.mRawPtr as *const DomMediaList; if dom_media_list.is_null() { return None;
} let list = &*(*dom_media_list).mRawList.mRawPtr;
Some(list.read_with(guard))
}
}
// All the stylesheets Servo knows about are enabled, because that state is // handled externally by Gecko. #[inline] fn enabled(&self) -> bool { true
}
fn implicit_scope_root(&self) -> Option<ImplicitScopeRoot> { unsafe { let result = bindings::Gecko_StyleSheet_ImplicitScopeRoot(self.0); if result.mRoot.is_null() { returnif result.mConstructed {
Some(ImplicitScopeRoot::Constructed)
} else { // Could be genuinely not attached, like user stylesheet.
None
};
}
let root = GeckoElement(result.mRoot.as_ref().unwrap()).opaque();
Some(if !result.mHost.is_null() { let host = GeckoElement(result.mHost.as_ref().unwrap()).opaque(); if host == root {
ImplicitScopeRoot::ShadowHost(root)
} else {
ImplicitScopeRoot::InShadowTree(root)
}
} else {
ImplicitScopeRoot::InLightTree(root)
})
}
}
}
/// The container for data that a Servo-backed Gecko document needs to style /// itself. pubstruct PerDocumentStyleDataImpl { /// Rule processor. pub stylist: Stylist,
/// A cache from element to resolved style. pub undisplayed_style_cache: crate::traversal::UndisplayedStyleCache,
/// The generation for which our cache is valid. pub undisplayed_style_cache_generation: u64,
}
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics /// and unexpected races while trying to mutate it. #[derive(Deref)] pubstruct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
impl PerDocumentStyleData { /// Create a `PerDocumentStyleData`. pubfn new(document: *const structs::Document) -> Self { let device = Device::new(document); let quirks_mode = device.document().mCompatMode;
/// Get an immutable reference to this style data. pubfn borrow(&self) -> AtomicRef<PerDocumentStyleDataImpl> { self.0.borrow()
}
/// Get an mutable reference to this style data. pubfn borrow_mut(&self) -> AtomicRefMut<PerDocumentStyleDataImpl> { self.0.borrow_mut()
}
}
impl PerDocumentStyleDataImpl { /// Recreate the style data if the stylesheets have changed. pubfn flush_stylesheets<E>(
&mutself,
guard: &SharedRwLockReadGuard,
document_element: Option<E>,
snapshots: Option<&SnapshotMap>,
) -> bool where
E: TElement,
{ self.stylist
.flush(&StylesheetGuards::same(guard), document_element, snapshots)
}
/// Get the default computed values for this document. pubfn default_computed_values(&self) -> &Arc<ComputedValues> { self.stylist.device().default_computed_values_arc()
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.