mirror of
https://github.com/servo/servo.git
synced 2025-10-11 05:50:19 +01:00
This patch makes the MallocSizeOf stuff in Stylo work more like the HeapSizeOf stuff already in Servo, except better. In particular, it adds deriving support for MallocSizeOf, which will make it easier to improve coverage. The patch does the following. - Combines servo/components/style/stylesheets/memory.rs and the heapsize crate into a new crate, malloc_size_of. - Forks the heapsize_derive crate, calling it malloc_size_of, so that MallocSizeOf can be derived. - Both the new crates have MIT/Apache licenses, like heapsize, in case they are incorporated into heapsize in the future. - Renames the methods within MallocSizeOf and the related traits so they are more concise. - Removes MallocSizeOfWithGuard. - Adds `derive(MallocSizeOf)` to a lot of types, in some cases replacing an equivalent or almost-equivalent hand-written implementation. - Adds stuff so that Rc/Arc can be handled properly.
200 lines
6.6 KiB
Rust
200 lines
6.6 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
//! Data needed to style a Gecko document.
|
|
|
|
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
|
use dom::TElement;
|
|
use gecko_bindings::bindings::{self, RawServoStyleSet};
|
|
use gecko_bindings::structs::{RawGeckoPresContextOwned, ServoStyleSetSizes, ServoStyleSheet};
|
|
use gecko_bindings::structs::{StyleSheetInfo, ServoStyleSheetInner};
|
|
use gecko_bindings::structs::nsIDocument;
|
|
use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
|
|
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
|
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
|
use media_queries::{Device, MediaList};
|
|
use properties::ComputedValues;
|
|
use servo_arc::Arc;
|
|
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
|
|
use stylesheets::{PerOrigin, StylesheetContents, StylesheetInDocument};
|
|
use stylist::{ExtraStyleData, Stylist};
|
|
|
|
/// Little wrapper to a Gecko style sheet.
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
pub struct GeckoStyleSheet(*const ServoStyleSheet);
|
|
|
|
impl ToMediaListKey for ::gecko::data::GeckoStyleSheet {
|
|
fn to_media_list_key(&self) -> MediaListKey {
|
|
use std::mem;
|
|
unsafe {
|
|
MediaListKey::from_raw(mem::transmute(self.0))
|
|
}
|
|
}
|
|
}
|
|
|
|
impl GeckoStyleSheet {
|
|
/// Create a `GeckoStyleSheet` from a raw `ServoStyleSheet` pointer.
|
|
#[inline]
|
|
pub unsafe fn new(s: *const ServoStyleSheet) -> Self {
|
|
debug_assert!(!s.is_null());
|
|
bindings::Gecko_StyleSheet_AddRef(s);
|
|
Self::from_addrefed(s)
|
|
}
|
|
|
|
/// Create a `GeckoStyleSheet` from a raw `ServoStyleSheet` pointer that
|
|
/// already holds a strong reference.
|
|
#[inline]
|
|
pub unsafe fn from_addrefed(s: *const ServoStyleSheet) -> Self {
|
|
debug_assert!(!s.is_null());
|
|
GeckoStyleSheet(s)
|
|
}
|
|
|
|
/// Get the raw `ServoStyleSheet` that we're wrapping.
|
|
pub fn raw(&self) -> &ServoStyleSheet {
|
|
unsafe { &*self.0 }
|
|
}
|
|
|
|
fn inner(&self) -> &ServoStyleSheetInner {
|
|
unsafe {
|
|
&*(self.raw()._base.mInner as *const StyleSheetInfo as *const ServoStyleSheetInner)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Drop for GeckoStyleSheet {
|
|
fn drop(&mut self) {
|
|
unsafe { bindings::Gecko_StyleSheet_Release(self.0) };
|
|
}
|
|
}
|
|
|
|
impl Clone for GeckoStyleSheet {
|
|
fn clone(&self) -> Self {
|
|
unsafe { bindings::Gecko_StyleSheet_AddRef(self.0) };
|
|
GeckoStyleSheet(self.0)
|
|
}
|
|
}
|
|
|
|
impl StylesheetInDocument for GeckoStyleSheet {
|
|
fn contents(&self, _: &SharedRwLockReadGuard) -> &StylesheetContents {
|
|
debug_assert!(!self.inner().mContents.mRawPtr.is_null());
|
|
unsafe {
|
|
let contents =
|
|
(&**StylesheetContents::as_arc(&&*self.inner().mContents.mRawPtr)) as *const _;
|
|
&*contents
|
|
}
|
|
}
|
|
|
|
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
|
|
use gecko_bindings::structs::ServoMediaList;
|
|
use std::mem;
|
|
|
|
unsafe {
|
|
let servo_media_list =
|
|
self.raw()._base.mMedia.mRawPtr as *const ServoMediaList;
|
|
if servo_media_list.is_null() {
|
|
return None;
|
|
}
|
|
let raw_list = &*(*servo_media_list).mRawList.mRawPtr;
|
|
let list = Locked::<MediaList>::as_arc(mem::transmute(&raw_list));
|
|
Some(list.read_with(guard))
|
|
}
|
|
}
|
|
|
|
// All the stylesheets Servo knows about are enabled, because that state is
|
|
// handled externally by Gecko.
|
|
fn enabled(&self) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
/// The container for data that a Servo-backed Gecko document needs to style
|
|
/// itself.
|
|
pub struct PerDocumentStyleDataImpl {
|
|
/// Rule processor.
|
|
pub stylist: Stylist,
|
|
|
|
/// List of effective @font-face and @counter-style rules.
|
|
pub extra_style_data: PerOrigin<ExtraStyleData>,
|
|
}
|
|
|
|
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
|
|
/// and unexpected races while trying to mutate it.
|
|
pub struct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
|
|
|
|
impl PerDocumentStyleData {
|
|
/// Create a dummy `PerDocumentStyleData`.
|
|
pub fn new(pres_context: RawGeckoPresContextOwned) -> Self {
|
|
let device = Device::new(pres_context);
|
|
let quirks_mode = unsafe {
|
|
(*device.pres_context().mDocument.raw::<nsIDocument>()).mCompatMode
|
|
};
|
|
|
|
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
|
|
stylist: Stylist::new(device, quirks_mode.into()),
|
|
extra_style_data: Default::default(),
|
|
}))
|
|
}
|
|
|
|
/// Get an immutable reference to this style data.
|
|
pub fn borrow(&self) -> AtomicRef<PerDocumentStyleDataImpl> {
|
|
self.0.borrow()
|
|
}
|
|
|
|
/// Get an mutable reference to this style data.
|
|
pub fn borrow_mut(&self) -> AtomicRefMut<PerDocumentStyleDataImpl> {
|
|
self.0.borrow_mut()
|
|
}
|
|
}
|
|
|
|
impl PerDocumentStyleDataImpl {
|
|
/// Recreate the style data if the stylesheets have changed.
|
|
pub fn flush_stylesheets<E>(
|
|
&mut self,
|
|
guard: &SharedRwLockReadGuard,
|
|
document_element: Option<E>,
|
|
) -> bool
|
|
where
|
|
E: TElement,
|
|
{
|
|
self.stylist.flush(
|
|
&StylesheetGuards::same(guard),
|
|
/* ua_sheets = */ None,
|
|
&mut self.extra_style_data,
|
|
document_element,
|
|
)
|
|
}
|
|
|
|
/// Returns whether private browsing is enabled.
|
|
pub fn is_private_browsing_enabled(&self) -> bool {
|
|
let doc =
|
|
self.stylist.device().pres_context().mDocument.raw::<nsIDocument>();
|
|
unsafe { bindings::Gecko_IsPrivateBrowsingEnabled(doc) }
|
|
}
|
|
|
|
/// Get the default computed values for this document.
|
|
pub fn default_computed_values(&self) -> &Arc<ComputedValues> {
|
|
self.stylist.device().default_computed_values_arc()
|
|
}
|
|
|
|
/// Returns whether visited links are enabled.
|
|
fn visited_links_enabled(&self) -> bool {
|
|
unsafe { bindings::Gecko_AreVisitedLinksEnabled() }
|
|
}
|
|
/// Returns whether visited styles are enabled.
|
|
pub fn visited_styles_enabled(&self) -> bool {
|
|
self.visited_links_enabled() && !self.is_private_browsing_enabled()
|
|
}
|
|
|
|
/// Measure heap usage.
|
|
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
|
|
self.stylist.add_size_of_children(ops, sizes);
|
|
sizes.mStylistOther += self.extra_style_data.size_of(ops);
|
|
}
|
|
}
|
|
|
|
unsafe impl HasFFI for PerDocumentStyleData {
|
|
type FFIType = RawServoStyleSet;
|
|
}
|
|
unsafe impl HasSimpleFFI for PerDocumentStyleData {}
|
|
unsafe impl HasBoxFFI for PerDocumentStyleData {}
|