mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Use PropertyDeclarationBlock in a DOMRefCell everywhere.
This commit is contained in:
parent
d4f704cad2
commit
d986fd2d2f
14 changed files with 146 additions and 100 deletions
|
@ -8,6 +8,7 @@
|
|||
|
||||
use atomic_refcell::{AtomicRef, AtomicRefMut};
|
||||
use data::PersistentStyleData;
|
||||
use domrefcell::DOMRefCell;
|
||||
use element_state::ElementState;
|
||||
use properties::{ComputedValues, PropertyDeclarationBlock};
|
||||
use restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
|
||||
|
@ -202,7 +203,7 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
|
|||
|
||||
fn as_node(&self) -> Self::ConcreteNode;
|
||||
|
||||
fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>>;
|
||||
fn style_attribute(&self) -> Option<&Arc<DOMRefCell<PropertyDeclarationBlock>>>;
|
||||
|
||||
fn get_state(&self) -> ElementState;
|
||||
|
||||
|
|
|
@ -11,12 +11,19 @@ use thread_state;
|
|||
///
|
||||
/// This extends the API of `core::cell::RefCell` to allow unsafe access in
|
||||
/// certain situations, with dynamic checking in debug builds.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct DOMRefCell<T> {
|
||||
value: RefCell<T>,
|
||||
}
|
||||
|
||||
// FIXME: These two impls make promises that are not quite true,
|
||||
// but maybe the debug_assert! makes it close enough.
|
||||
#[allow(unsafe_code)]
|
||||
unsafe impl<T: Send> Send for DOMRefCell<T> {}
|
||||
#[allow(unsafe_code)]
|
||||
unsafe impl<T: Sync> Sync for DOMRefCell<T> {}
|
||||
|
||||
// Functionality specific to Servo's `DOMRefCell` type
|
||||
// ===================================================
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ use std::ptr;
|
|||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, AtomicPtr};
|
||||
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
||||
use style::domrefcell::DOMRefCell;
|
||||
use url::Url;
|
||||
|
||||
pub struct NonOpaqueStyleData(AtomicRefCell<PersistentStyleData>);
|
||||
|
@ -468,7 +469,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
|
||||
}
|
||||
|
||||
fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>> {
|
||||
fn style_attribute(&self) -> Option<&Arc<DOMRefCell<PropertyDeclarationBlock>>> {
|
||||
let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.0) };
|
||||
if declarations.is_null() {
|
||||
None
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
|
||||
use cssparser::{DeclarationListParser, DeclarationParser};
|
||||
use domrefcell::DOMRefCell;
|
||||
use parser::{ParserContext, log_css_error};
|
||||
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
|
||||
use properties::PropertyDeclarationParseResult;
|
||||
|
@ -78,7 +79,7 @@ pub struct Keyframe {
|
|||
/// But including them enables `compute_style_for_animation_step` to create a `ApplicableDeclarationBlock`
|
||||
/// by cloning an `Arc<_>` (incrementing a reference count) rather than re-creating a `Vec<_>`.
|
||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||
pub block: Arc<PropertyDeclarationBlock>,
|
||||
pub block: Arc<DOMRefCell<PropertyDeclarationBlock>>,
|
||||
}
|
||||
|
||||
/// A keyframes step value. This can be a synthetised keyframes animation, that
|
||||
|
@ -89,7 +90,7 @@ pub struct Keyframe {
|
|||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum KeyframesStepValue {
|
||||
/// See `Keyframe::declarations`’s docs about the presence of `Importance`.
|
||||
Declarations(Arc<PropertyDeclarationBlock>),
|
||||
Declarations(Arc<DOMRefCell<PropertyDeclarationBlock>>),
|
||||
ComputedValues,
|
||||
}
|
||||
|
||||
|
@ -110,12 +111,14 @@ pub struct KeyframesStep {
|
|||
}
|
||||
|
||||
impl KeyframesStep {
|
||||
#[allow(unsafe_code)]
|
||||
#[inline]
|
||||
fn new(percentage: KeyframePercentage,
|
||||
value: KeyframesStepValue) -> Self {
|
||||
let declared_timing_function = match value {
|
||||
KeyframesStepValue::Declarations(ref block) => {
|
||||
block.declarations.iter().any(|&(ref prop_decl, _)| {
|
||||
// FIXME: Is this thread-safe?
|
||||
unsafe { block.borrow_for_layout() }.declarations.iter().any(|&(ref prop_decl, _)| {
|
||||
match *prop_decl {
|
||||
PropertyDeclaration::AnimationTimingFunction(..) => true,
|
||||
_ => false,
|
||||
|
@ -151,11 +154,13 @@ pub struct KeyframesAnimation {
|
|||
///
|
||||
/// In practice, browsers seem to try to do their best job at it, so we might
|
||||
/// want to go through all the actual keyframes and deduplicate properties.
|
||||
#[allow(unsafe_code)]
|
||||
fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> {
|
||||
let mut ret = vec![];
|
||||
// NB: declarations are already deduplicated, so we don't have to check for
|
||||
// it here.
|
||||
for &(ref declaration, _) in keyframe.block.declarations.iter() {
|
||||
// FIXME: Is this thread-safe?
|
||||
for &(ref declaration, _) in unsafe { keyframe.block.borrow_for_layout() }.declarations.iter() {
|
||||
if let Some(property) = TransitionProperty::from_declaration(declaration) {
|
||||
ret.push(property);
|
||||
}
|
||||
|
@ -266,10 +271,10 @@ impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
|
|||
}
|
||||
Ok(Arc::new(Keyframe {
|
||||
selector: prelude,
|
||||
block: Arc::new(PropertyDeclarationBlock {
|
||||
block: Arc::new(DOMRefCell::new(PropertyDeclarationBlock {
|
||||
declarations: declarations,
|
||||
important_count: 0,
|
||||
}),
|
||||
})),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ use sink::ForgetfulSink;
|
|||
use smallvec::SmallVec;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
use std::slice::IterMut;
|
||||
use std::sync::Arc;
|
||||
use string_cache::Atom;
|
||||
|
@ -139,7 +140,7 @@ impl<'a> Hash for ApplicableDeclarationsCacheQuery<'a> {
|
|||
for declaration in self.declarations {
|
||||
// Each declaration contians an Arc, which is a stable
|
||||
// pointer; we use that for hashing and equality.
|
||||
let ptr: *const PropertyDeclarationBlock = &*declaration.mixed_declarations;
|
||||
let ptr: *const _ = Arc::deref(&declaration.mixed_declarations);
|
||||
ptr.hash(state);
|
||||
declaration.importance.hash(state);
|
||||
}
|
||||
|
|
|
@ -311,6 +311,10 @@ impl PropertyDeclarationBlock {
|
|||
pub fn any_normal(&self) -> bool {
|
||||
self.declarations.len() > self.important_count as usize
|
||||
}
|
||||
|
||||
pub fn get(&self, property_name: &str) -> Option< &(PropertyDeclaration, Importance)> {
|
||||
self.declarations.iter().find(|&&(ref decl, _)| decl.matches(property_name))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for PropertyDeclarationBlock {
|
||||
|
@ -741,7 +745,7 @@ impl Shorthand {
|
|||
|
||||
/// Serializes possible shorthand value to String.
|
||||
pub fn serialize_shorthand_value_to_string<'a, I>(self, declarations: I, importance: Importance) -> String
|
||||
where I: Iterator<Item=&'a PropertyDeclaration> + Clone {
|
||||
where I: IntoIterator<Item=&'a PropertyDeclaration>, I::IntoIter: Clone {
|
||||
let appendable_value = self.get_shorthand_appendable_value(declarations).unwrap();
|
||||
let mut result = String::new();
|
||||
append_declaration_value(&mut result, appendable_value, importance).unwrap();
|
||||
|
@ -755,7 +759,7 @@ impl Shorthand {
|
|||
declarations: I,
|
||||
is_first_serialization: &mut bool)
|
||||
-> Result<bool, fmt::Error>
|
||||
where W: Write, I: Iterator<Item=&'a PropertyDeclaration> + Clone {
|
||||
where W: Write, I: IntoIterator<Item=&'a PropertyDeclaration>, I::IntoIter: Clone {
|
||||
match self.get_shorthand_appendable_value(declarations) {
|
||||
None => Ok(false),
|
||||
Some(appendable_value) => {
|
||||
|
@ -772,8 +776,10 @@ impl Shorthand {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_shorthand_appendable_value<'a, I>(self, declarations: I) -> Option<AppendableValue<'a, I>>
|
||||
where I: Iterator<Item=&'a PropertyDeclaration> + Clone {
|
||||
fn get_shorthand_appendable_value<'a, I>(self, declarations: I)
|
||||
-> Option<AppendableValue<'a, I::IntoIter>>
|
||||
where I: IntoIterator<Item=&'a PropertyDeclaration>, I::IntoIter: Clone {
|
||||
let declarations = declarations.into_iter();
|
||||
|
||||
// Only cloning iterators (a few pointers each) not declarations.
|
||||
let mut declarations2 = declarations.clone();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
//! Selector matching.
|
||||
|
||||
use dom::PresentationalHintsSynthetizer;
|
||||
use domrefcell::DOMRefCell;
|
||||
use element_state::*;
|
||||
use error_reporting::StdoutErrorReporter;
|
||||
use keyframes::KeyframesAnimation;
|
||||
|
@ -178,7 +179,7 @@ impl Stylist {
|
|||
|
||||
map.insert(Rule {
|
||||
selector: selector.complex_selector.clone(),
|
||||
declarations: style_rule.declarations.clone(),
|
||||
declarations: style_rule.block.clone(),
|
||||
specificity: selector.specificity,
|
||||
source_order: rules_source_order,
|
||||
});
|
||||
|
@ -327,11 +328,12 @@ impl Stylist {
|
|||
/// that is, whether the matched selectors are simple enough to allow the
|
||||
/// matching logic to be reduced to the logic in
|
||||
/// `css::matching::PrivateMatchMethods::candidate_element_allows_for_style_sharing`.
|
||||
#[allow(unsafe_code)]
|
||||
pub fn push_applicable_declarations<E, V>(
|
||||
&self,
|
||||
element: &E,
|
||||
parent_bf: Option<&BloomFilter>,
|
||||
style_attribute: Option<&Arc<PropertyDeclarationBlock>>,
|
||||
style_attribute: Option<&Arc<DOMRefCell<PropertyDeclarationBlock>>>,
|
||||
pseudo_element: Option<&PseudoElement>,
|
||||
applicable_declarations: &mut V,
|
||||
reason: MatchingReason) -> StyleRelations
|
||||
|
@ -390,8 +392,9 @@ impl Stylist {
|
|||
debug!("author normal: {:?}", relations);
|
||||
|
||||
// Step 4: Normal style attributes.
|
||||
if let Some(sa) = style_attribute {
|
||||
if sa.any_normal() {
|
||||
if let Some(sa) = style_attribute {
|
||||
// FIXME: Is this thread-safe?
|
||||
if unsafe { sa.borrow_for_layout() }.any_normal() {
|
||||
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
|
||||
Push::push(
|
||||
applicable_declarations,
|
||||
|
@ -413,7 +416,8 @@ impl Stylist {
|
|||
|
||||
// Step 6: `!important` style attributes.
|
||||
if let Some(sa) = style_attribute {
|
||||
if sa.any_important() {
|
||||
// FIXME: Is this thread-safe?
|
||||
if unsafe { sa.borrow_for_layout() }.any_important() {
|
||||
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
|
||||
Push::push(
|
||||
applicable_declarations,
|
||||
|
@ -691,6 +695,7 @@ impl SelectorMap {
|
|||
|
||||
/// Append to `rule_list` all universal Rules (rules with selector `*|*`) in
|
||||
/// `self` sorted by specifity and source order.
|
||||
#[allow(unsafe_code)]
|
||||
pub fn get_universal_rules<V>(&self,
|
||||
matching_rules_list: &mut V)
|
||||
where V: VecLike<ApplicableDeclarationBlock>
|
||||
|
@ -704,11 +709,13 @@ impl SelectorMap {
|
|||
for rule in self.other_rules.iter() {
|
||||
if rule.selector.compound_selector.is_empty() &&
|
||||
rule.selector.next.is_none() {
|
||||
if rule.declarations.any_normal() {
|
||||
// FIXME: Is this thread-safe?
|
||||
let block = unsafe { rule.declarations.borrow_for_layout() };
|
||||
if block.any_normal() {
|
||||
matching_rules_list.push(
|
||||
rule.to_applicable_declaration_block(Importance::Normal));
|
||||
}
|
||||
if rule.declarations.any_important() {
|
||||
if block.any_important() {
|
||||
matching_rules_list.push(
|
||||
rule.to_applicable_declaration_block(Importance::Important));
|
||||
}
|
||||
|
@ -745,6 +752,7 @@ impl SelectorMap {
|
|||
}
|
||||
|
||||
/// Adds rules in `rules` that match `element` to the `matching_rules` list.
|
||||
#[allow(unsafe_code)]
|
||||
fn get_matching_rules<E, V>(element: &E,
|
||||
parent_bf: Option<&BloomFilter>,
|
||||
rules: &[Rule],
|
||||
|
@ -756,7 +764,8 @@ impl SelectorMap {
|
|||
V: VecLike<ApplicableDeclarationBlock>
|
||||
{
|
||||
for rule in rules.iter() {
|
||||
let block = &rule.declarations;
|
||||
// FIXME: Is this thread-safe?
|
||||
let block = unsafe { rule.declarations.borrow_for_layout() };
|
||||
let any_declaration_for_importance = if importance.important() {
|
||||
block.any_important()
|
||||
} else {
|
||||
|
@ -844,7 +853,7 @@ pub struct Rule {
|
|||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||
pub selector: Arc<ComplexSelector<TheSelectorImpl>>,
|
||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||
pub declarations: Arc<PropertyDeclarationBlock>,
|
||||
pub declarations: Arc<DOMRefCell<PropertyDeclarationBlock>>,
|
||||
pub source_order: usize,
|
||||
pub specificity: u32,
|
||||
}
|
||||
|
@ -869,7 +878,7 @@ pub struct ApplicableDeclarationBlock {
|
|||
/// Contains declarations of either importance, but only those of self.importance are relevant.
|
||||
/// Use ApplicableDeclarationBlock::iter
|
||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||
pub mixed_declarations: Arc<PropertyDeclarationBlock>,
|
||||
pub mixed_declarations: Arc<DOMRefCell<PropertyDeclarationBlock>>,
|
||||
pub importance: Importance,
|
||||
pub source_order: usize,
|
||||
pub specificity: u32,
|
||||
|
@ -877,7 +886,7 @@ pub struct ApplicableDeclarationBlock {
|
|||
|
||||
impl ApplicableDeclarationBlock {
|
||||
#[inline]
|
||||
pub fn from_declarations(declarations: Arc<PropertyDeclarationBlock>,
|
||||
pub fn from_declarations(declarations: Arc<DOMRefCell<PropertyDeclarationBlock>>,
|
||||
importance: Importance)
|
||||
-> Self {
|
||||
ApplicableDeclarationBlock {
|
||||
|
@ -888,9 +897,11 @@ impl ApplicableDeclarationBlock {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn iter(&self) -> ApplicableDeclarationBlockIter {
|
||||
ApplicableDeclarationBlockIter {
|
||||
iter: self.mixed_declarations.declarations.iter(),
|
||||
// FIXME: Is this thread-safe?
|
||||
iter: unsafe { self.mixed_declarations.borrow_for_layout() }.declarations.iter(),
|
||||
importance: self.importance,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, decode_stylesheet_bytes};
|
||||
use cssparser::{AtRuleType, RuleListParser, Token};
|
||||
use domrefcell::DOMRefCell;
|
||||
use encoding::EncodingRef;
|
||||
use error_reporting::ParseErrorReporter;
|
||||
use font_face::{FontFaceRule, parse_font_face_block};
|
||||
|
@ -106,7 +107,7 @@ impl MediaRule {
|
|||
#[derive(Debug, PartialEq)]
|
||||
pub struct StyleRule {
|
||||
pub selectors: Vec<Selector<TheSelectorImpl>>,
|
||||
pub declarations: Arc<PropertyDeclarationBlock>,
|
||||
pub block: Arc<DOMRefCell<PropertyDeclarationBlock>>,
|
||||
}
|
||||
|
||||
|
||||
|
@ -558,7 +559,7 @@ impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
|
|||
-> Result<CSSRule, ()> {
|
||||
Ok(CSSRule::Style(Arc::new(StyleRule {
|
||||
selectors: prelude,
|
||||
declarations: Arc::new(parse_property_declaration_list(self.context, input))
|
||||
block: Arc::new(DOMRefCell::new(parse_property_declaration_list(self.context, input)))
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue