mirror of
https://github.com/servo/servo.git
synced 2025-07-03 21:43:41 +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
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::ToCss;
|
use cssparser::ToCss;
|
||||||
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::{self, CSSStyleDeclarationMethods};
|
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::{self, CSSStyleDeclarationMethods};
|
||||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||||
use dom::bindings::global::GlobalRef;
|
use dom::bindings::global::GlobalRef;
|
||||||
|
@ -14,13 +15,11 @@ use dom::element::Element;
|
||||||
use dom::node::{Node, NodeDamage, window_from_node};
|
use dom::node::{Node, NodeDamage, window_from_node};
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::slice;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
use style::parser::ParserContextExtraData;
|
use style::parser::ParserContextExtraData;
|
||||||
use style::properties::{PropertyDeclaration, Shorthand, Importance};
|
use style::properties::{Shorthand, Importance};
|
||||||
use style::properties::{is_supported_property, parse_one_declaration, parse_style_attribute};
|
use style::properties::{is_supported_property, parse_one_declaration, parse_style_attribute};
|
||||||
use style::refcell::Ref;
|
|
||||||
use style::selector_impl::PseudoElement;
|
use style::selector_impl::PseudoElement;
|
||||||
|
|
||||||
// http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
|
// http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
|
||||||
|
@ -93,7 +92,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
fn Length(&self) -> u32 {
|
fn Length(&self) -> u32 {
|
||||||
let elem = self.owner.upcast::<Element>();
|
let elem = self.owner.upcast::<Element>();
|
||||||
let len = match *elem.style_attribute().borrow() {
|
let len = match *elem.style_attribute().borrow() {
|
||||||
Some(ref declarations) => declarations.declarations.len(),
|
Some(ref declarations) => declarations.borrow().declarations.len(),
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
len as u32
|
len as u32
|
||||||
|
@ -119,43 +118,42 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
if let Some(shorthand) = Shorthand::from_name(&property) {
|
if let Some(shorthand) = Shorthand::from_name(&property) {
|
||||||
|
let style_attribute = owner.style_attribute().borrow();
|
||||||
|
let style_attribute = if let Some(ref style_attribute) = *style_attribute {
|
||||||
|
style_attribute.borrow()
|
||||||
|
} else {
|
||||||
|
// shorthand.longhands() is never empty, so with no style attribute
|
||||||
|
// step 2.2.2 would do this:
|
||||||
|
return DOMString::new()
|
||||||
|
};
|
||||||
|
|
||||||
// Step 2.1
|
// Step 2.1
|
||||||
let mut list = vec![];
|
let mut list = vec![];
|
||||||
|
|
||||||
// Step 2.2
|
// Step 2.2
|
||||||
for longhand in shorthand.longhands() {
|
for longhand in shorthand.longhands() {
|
||||||
// Step 2.2.1
|
// Step 2.2.1
|
||||||
let declaration = owner.get_inline_style_declaration(&Atom::from(*longhand));
|
let declaration = style_attribute.get(longhand);
|
||||||
|
|
||||||
// Step 2.2.2 & 2.2.3
|
// Step 2.2.2 & 2.2.3
|
||||||
match declaration {
|
match declaration {
|
||||||
Some(declaration) => list.push(declaration),
|
Some(&(ref declaration, _importance)) => list.push(declaration),
|
||||||
None => return DOMString::new(),
|
None => return DOMString::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2.3
|
// Step 2.3
|
||||||
// Work around closures not being Clone
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Map<'a, 'b: 'a>(slice::Iter<'a, Ref<'b, (PropertyDeclaration, Importance)>>);
|
|
||||||
impl<'a, 'b> Iterator for Map<'a, 'b> {
|
|
||||||
type Item = &'a PropertyDeclaration;
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
self.0.next().map(|r| &r.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: important is hardcoded to false because method does not implement it yet
|
// TODO: important is hardcoded to false because method does not implement it yet
|
||||||
let serialized_value = shorthand.serialize_shorthand_value_to_string(
|
let serialized_value = shorthand.serialize_shorthand_value_to_string(
|
||||||
Map(list.iter()), Importance::Normal);
|
list, Importance::Normal);
|
||||||
return DOMString::from(serialized_value);
|
return DOMString::from(serialized_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3 & 4
|
// Step 3 & 4
|
||||||
match owner.get_inline_style_declaration(&property) {
|
owner.get_inline_style_declaration(&property, |d| match d {
|
||||||
Some(declaration) => DOMString::from(declaration.0.value()),
|
Some(declaration) => DOMString::from(declaration.0.value()),
|
||||||
None => DOMString::new(),
|
None => DOMString::new(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority
|
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority
|
||||||
|
@ -172,13 +170,18 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
.all(|priority| priority == "important") {
|
.all(|priority| priority == "important") {
|
||||||
return DOMString::from("important");
|
return DOMString::from("important");
|
||||||
}
|
}
|
||||||
// Step 3
|
|
||||||
} else {
|
} else {
|
||||||
if let Some(decl) = self.owner.get_inline_style_declaration(&property) {
|
// Step 3
|
||||||
if decl.1.important() {
|
return self.owner.get_inline_style_declaration(&property, |d| {
|
||||||
return DOMString::from("important");
|
if let Some(decl) = d {
|
||||||
|
if decl.1.important() {
|
||||||
|
return DOMString::from("important");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// Step 4
|
||||||
|
DOMString::new()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4
|
// Step 4
|
||||||
|
@ -328,13 +331,14 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
let elem = self.owner.upcast::<Element>();
|
let elem = self.owner.upcast::<Element>();
|
||||||
let style_attribute = elem.style_attribute().borrow();
|
let style_attribute = elem.style_attribute().borrow();
|
||||||
style_attribute.as_ref().and_then(|declarations| {
|
style_attribute.as_ref().and_then(|declarations| {
|
||||||
declarations.declarations.get(index)
|
declarations.borrow().declarations.get(index).map(|entry| {
|
||||||
}).map(|&(ref declaration, importance)| {
|
let (ref declaration, importance) = *entry;
|
||||||
let mut css = declaration.to_css_string();
|
let mut css = declaration.to_css_string();
|
||||||
if importance.important() {
|
if importance.important() {
|
||||||
css += " !important";
|
css += " !important";
|
||||||
}
|
}
|
||||||
DOMString::from(css)
|
DOMString::from(css)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +348,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
let style_attribute = elem.style_attribute().borrow();
|
let style_attribute = elem.style_attribute().borrow();
|
||||||
|
|
||||||
if let Some(declarations) = style_attribute.as_ref() {
|
if let Some(declarations) = style_attribute.as_ref() {
|
||||||
DOMString::from(declarations.to_css_string())
|
DOMString::from(declarations.borrow().to_css_string())
|
||||||
} else {
|
} else {
|
||||||
DOMString::new()
|
DOMString::new()
|
||||||
}
|
}
|
||||||
|
@ -366,7 +370,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
|
||||||
*element.style_attribute().borrow_mut() = if decl_block.declarations.is_empty() {
|
*element.style_attribute().borrow_mut() = if decl_block.declarations.is_empty() {
|
||||||
None // Step 2
|
None // Step 2
|
||||||
} else {
|
} else {
|
||||||
Some(Arc::new(decl_block))
|
Some(Arc::new(DOMRefCell::new(decl_block)))
|
||||||
};
|
};
|
||||||
element.sync_property_with_attrs_style();
|
element.sync_property_with_attrs_style();
|
||||||
let node = element.upcast::<Node>();
|
let node = element.upcast::<Node>();
|
||||||
|
|
|
@ -110,7 +110,7 @@ pub struct Element {
|
||||||
attrs: DOMRefCell<Vec<JS<Attr>>>,
|
attrs: DOMRefCell<Vec<JS<Attr>>>,
|
||||||
id_attribute: DOMRefCell<Option<Atom>>,
|
id_attribute: DOMRefCell<Option<Atom>>,
|
||||||
#[ignore_heap_size_of = "Arc"]
|
#[ignore_heap_size_of = "Arc"]
|
||||||
style_attribute: DOMRefCell<Option<Arc<PropertyDeclarationBlock>>>,
|
style_attribute: DOMRefCell<Option<Arc<DOMRefCell<PropertyDeclarationBlock>>>>,
|
||||||
attr_list: MutNullableHeap<JS<NamedNodeMap>>,
|
attr_list: MutNullableHeap<JS<NamedNodeMap>>,
|
||||||
class_list: MutNullableHeap<JS<DOMTokenList>>,
|
class_list: MutNullableHeap<JS<DOMTokenList>>,
|
||||||
state: Cell<ElementState>,
|
state: Cell<ElementState>,
|
||||||
|
@ -298,7 +298,7 @@ pub trait LayoutElementHelpers {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn html_element_in_html_document_for_layout(&self) -> bool;
|
unsafe fn html_element_in_html_document_for_layout(&self) -> bool;
|
||||||
fn id_attribute(&self) -> *const Option<Atom>;
|
fn id_attribute(&self) -> *const Option<Atom>;
|
||||||
fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>>;
|
fn style_attribute(&self) -> *const Option<Arc<DOMRefCell<PropertyDeclarationBlock>>>;
|
||||||
fn local_name(&self) -> &Atom;
|
fn local_name(&self) -> &Atom;
|
||||||
fn namespace(&self) -> &Namespace;
|
fn namespace(&self) -> &Namespace;
|
||||||
fn get_checked_state_for_layout(&self) -> bool;
|
fn get_checked_state_for_layout(&self) -> bool;
|
||||||
|
@ -330,10 +330,10 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_declaration(rule: PropertyDeclaration) -> ApplicableDeclarationBlock {
|
fn from_declaration(rule: PropertyDeclaration) -> ApplicableDeclarationBlock {
|
||||||
ApplicableDeclarationBlock::from_declarations(
|
ApplicableDeclarationBlock::from_declarations(
|
||||||
Arc::new(PropertyDeclarationBlock {
|
Arc::new(DOMRefCell::new(PropertyDeclarationBlock {
|
||||||
declarations: vec![(rule, Importance::Normal)],
|
declarations: vec![(rule, Importance::Normal)],
|
||||||
important_count: 0,
|
important_count: 0,
|
||||||
}),
|
})),
|
||||||
Importance::Normal)
|
Importance::Normal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,7 +619,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>> {
|
fn style_attribute(&self) -> *const Option<Arc<DOMRefCell<PropertyDeclarationBlock>>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.unsafe_get()).style_attribute.borrow_for_layout()
|
(*self.unsafe_get()).style_attribute.borrow_for_layout()
|
||||||
}
|
}
|
||||||
|
@ -708,7 +708,7 @@ impl Element {
|
||||||
self.attrs.borrow()
|
self.attrs.borrow()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn style_attribute(&self) -> &DOMRefCell<Option<Arc<PropertyDeclarationBlock>>> {
|
pub fn style_attribute(&self) -> &DOMRefCell<Option<Arc<DOMRefCell<PropertyDeclarationBlock>>>> {
|
||||||
&self.style_attribute
|
&self.style_attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,7 +738,7 @@ impl Element {
|
||||||
// therefore, it should not trigger subsequent mutation events
|
// therefore, it should not trigger subsequent mutation events
|
||||||
pub fn sync_property_with_attrs_style(&self) {
|
pub fn sync_property_with_attrs_style(&self) {
|
||||||
let style_str = if let &Some(ref declarations) = &*self.style_attribute().borrow() {
|
let style_str = if let &Some(ref declarations) = &*self.style_attribute().borrow() {
|
||||||
declarations.to_css_string()
|
declarations.borrow().to_css_string()
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
@ -770,7 +770,7 @@ impl Element {
|
||||||
let mut inline_declarations = element.style_attribute.borrow_mut();
|
let mut inline_declarations = element.style_attribute.borrow_mut();
|
||||||
if let &mut Some(ref mut declarations) = &mut *inline_declarations {
|
if let &mut Some(ref mut declarations) = &mut *inline_declarations {
|
||||||
let mut importance = None;
|
let mut importance = None;
|
||||||
let index = declarations.declarations.iter().position(|&(ref decl, i)| {
|
let index = declarations.borrow().declarations.iter().position(|&(ref decl, i)| {
|
||||||
let matching = decl.matches(property);
|
let matching = decl.matches(property);
|
||||||
if matching {
|
if matching {
|
||||||
importance = Some(i)
|
importance = Some(i)
|
||||||
|
@ -778,7 +778,7 @@ impl Element {
|
||||||
matching
|
matching
|
||||||
});
|
});
|
||||||
if let Some(index) = index {
|
if let Some(index) = index {
|
||||||
let declarations = Arc::make_mut(declarations);
|
let mut declarations = Arc::make_mut(declarations).borrow_mut();
|
||||||
declarations.declarations.remove(index);
|
declarations.declarations.remove(index);
|
||||||
if importance.unwrap().important() {
|
if importance.unwrap().important() {
|
||||||
declarations.important_count -= 1;
|
declarations.important_count -= 1;
|
||||||
|
@ -801,7 +801,8 @@ impl Element {
|
||||||
{
|
{
|
||||||
// Usually, the reference count will be 1 here. But transitions could make it greater
|
// Usually, the reference count will be 1 here. But transitions could make it greater
|
||||||
// than that.
|
// than that.
|
||||||
let declaration_block = Arc::make_mut(declaration_block);
|
let mut declaration_block = Arc::make_mut(declaration_block).borrow_mut();
|
||||||
|
let declaration_block = &mut *declaration_block;
|
||||||
let existing_declarations = &mut declaration_block.declarations;
|
let existing_declarations = &mut declaration_block.declarations;
|
||||||
|
|
||||||
'outer: for incoming_declaration in declarations {
|
'outer: for incoming_declaration in declarations {
|
||||||
|
@ -835,10 +836,10 @@ impl Element {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
*inline_declarations = Some(Arc::new(PropertyDeclarationBlock {
|
*inline_declarations = Some(Arc::new(DOMRefCell::new(PropertyDeclarationBlock {
|
||||||
declarations: declarations.into_iter().map(|d| (d, importance)).collect(),
|
declarations: declarations.into_iter().map(|d| (d, importance)).collect(),
|
||||||
important_count: important_count,
|
important_count: important_count,
|
||||||
}));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
update(self, declarations, importance);
|
update(self, declarations, importance);
|
||||||
|
@ -853,7 +854,8 @@ impl Element {
|
||||||
if let &mut Some(ref mut block) = &mut *inline_declarations {
|
if let &mut Some(ref mut block) = &mut *inline_declarations {
|
||||||
// Usually, the reference counts of `from` and `to` will be 1 here. But transitions
|
// Usually, the reference counts of `from` and `to` will be 1 here. But transitions
|
||||||
// could make them greater than that.
|
// could make them greater than that.
|
||||||
let block = Arc::make_mut(block);
|
let mut block = Arc::make_mut(block).borrow_mut();
|
||||||
|
let block = &mut *block;
|
||||||
let declarations = &mut block.declarations;
|
let declarations = &mut block.declarations;
|
||||||
for &mut (ref declaration, ref mut importance) in declarations {
|
for &mut (ref declaration, ref mut importance) in declarations {
|
||||||
if properties.iter().any(|p| declaration.name() == **p) {
|
if properties.iter().any(|p| declaration.name() == **p) {
|
||||||
|
@ -875,16 +877,15 @@ impl Element {
|
||||||
self.sync_property_with_attrs_style();
|
self.sync_property_with_attrs_style();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_inline_style_declaration(&self,
|
pub fn get_inline_style_declaration<F, R>(&self, property: &str, f: F) -> R
|
||||||
property: &Atom)
|
where F: FnOnce(Option<&(PropertyDeclaration, Importance)>) -> R {
|
||||||
-> Option<Ref<(PropertyDeclaration, Importance)>> {
|
let style_attr = self.style_attribute.borrow();
|
||||||
Ref::filter_map(self.style_attribute.borrow(), |inline_declarations| {
|
if let Some(ref block) = *style_attr {
|
||||||
inline_declarations.as_ref().and_then(|declarations| {
|
let block = block.borrow();
|
||||||
declarations.declarations
|
f(block.get(property))
|
||||||
.iter()
|
} else {
|
||||||
.find(|&&(ref decl, _)| decl.matches(&property))
|
f(None)
|
||||||
})
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize(&self, traversal_scope: TraversalScope) -> Fallible<DOMString> {
|
pub fn serialize(&self, traversal_scope: TraversalScope) -> Fallible<DOMString> {
|
||||||
|
@ -2130,11 +2131,11 @@ impl VirtualMethods for Element {
|
||||||
*self.style_attribute.borrow_mut() =
|
*self.style_attribute.borrow_mut() =
|
||||||
mutation.new_value(attr).map(|value| {
|
mutation.new_value(attr).map(|value| {
|
||||||
let win = window_from_node(self);
|
let win = window_from_node(self);
|
||||||
Arc::new(parse_style_attribute(
|
Arc::new(DOMRefCell::new(parse_style_attribute(
|
||||||
&value,
|
&value,
|
||||||
&doc.base_url(),
|
&doc.base_url(),
|
||||||
win.css_error_reporter(),
|
win.css_error_reporter(),
|
||||||
ParserContextExtraData::default()))
|
ParserContextExtraData::default())))
|
||||||
});
|
});
|
||||||
if node.is_in_doc() {
|
if node.is_in_doc() {
|
||||||
node.dirty(NodeDamage::NodeStyleDamaged);
|
node.dirty(NodeDamage::NodeStyleDamaged);
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::inheritance::{CharacterDataTypeId, ElementTypeId};
|
use dom::bindings::inheritance::{CharacterDataTypeId, ElementTypeId};
|
||||||
use dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId};
|
use dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId};
|
||||||
use dom::bindings::js::LayoutJS;
|
use dom::bindings::js::LayoutJS;
|
||||||
|
@ -461,7 +462,7 @@ impl<'le> TElement for ServoLayoutElement<'le> {
|
||||||
ServoLayoutNode::from_layout_js(self.element.upcast())
|
ServoLayoutNode::from_layout_js(self.element.upcast())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>> {
|
fn style_attribute(&self) -> Option<&Arc<DOMRefCell<PropertyDeclarationBlock>>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.element.style_attribute()).as_ref()
|
(*self.element.style_attribute()).as_ref()
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
use atomic_refcell::{AtomicRef, AtomicRefMut};
|
use atomic_refcell::{AtomicRef, AtomicRefMut};
|
||||||
use data::PersistentStyleData;
|
use data::PersistentStyleData;
|
||||||
|
use domrefcell::DOMRefCell;
|
||||||
use element_state::ElementState;
|
use element_state::ElementState;
|
||||||
use properties::{ComputedValues, PropertyDeclarationBlock};
|
use properties::{ComputedValues, PropertyDeclarationBlock};
|
||||||
use restyle_hints::{RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint};
|
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 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;
|
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
|
/// This extends the API of `core::cell::RefCell` to allow unsafe access in
|
||||||
/// certain situations, with dynamic checking in debug builds.
|
/// certain situations, with dynamic checking in debug builds.
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub struct DOMRefCell<T> {
|
pub struct DOMRefCell<T> {
|
||||||
value: RefCell<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
|
// Functionality specific to Servo's `DOMRefCell` type
|
||||||
// ===================================================
|
// ===================================================
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ use std::ptr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicPtr};
|
use std::sync::atomic::{AtomicBool, AtomicPtr};
|
||||||
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
||||||
|
use style::domrefcell::DOMRefCell;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub struct NonOpaqueStyleData(AtomicRefCell<PersistentStyleData>);
|
pub struct NonOpaqueStyleData(AtomicRefCell<PersistentStyleData>);
|
||||||
|
@ -468,7 +469,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
|
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) };
|
let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.0) };
|
||||||
if declarations.is_null() {
|
if declarations.is_null() {
|
||||||
None
|
None
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
|
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
|
||||||
use cssparser::{DeclarationListParser, DeclarationParser};
|
use cssparser::{DeclarationListParser, DeclarationParser};
|
||||||
|
use domrefcell::DOMRefCell;
|
||||||
use parser::{ParserContext, log_css_error};
|
use parser::{ParserContext, log_css_error};
|
||||||
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
|
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
|
||||||
use properties::PropertyDeclarationParseResult;
|
use properties::PropertyDeclarationParseResult;
|
||||||
|
@ -78,7 +79,7 @@ pub struct Keyframe {
|
||||||
/// But including them enables `compute_style_for_animation_step` to create a `ApplicableDeclarationBlock`
|
/// 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<_>`.
|
/// by cloning an `Arc<_>` (incrementing a reference count) rather than re-creating a `Vec<_>`.
|
||||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
#[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
|
/// 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))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum KeyframesStepValue {
|
pub enum KeyframesStepValue {
|
||||||
/// See `Keyframe::declarations`’s docs about the presence of `Importance`.
|
/// See `Keyframe::declarations`’s docs about the presence of `Importance`.
|
||||||
Declarations(Arc<PropertyDeclarationBlock>),
|
Declarations(Arc<DOMRefCell<PropertyDeclarationBlock>>),
|
||||||
ComputedValues,
|
ComputedValues,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,12 +111,14 @@ pub struct KeyframesStep {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeyframesStep {
|
impl KeyframesStep {
|
||||||
|
#[allow(unsafe_code)]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(percentage: KeyframePercentage,
|
fn new(percentage: KeyframePercentage,
|
||||||
value: KeyframesStepValue) -> Self {
|
value: KeyframesStepValue) -> Self {
|
||||||
let declared_timing_function = match value {
|
let declared_timing_function = match value {
|
||||||
KeyframesStepValue::Declarations(ref block) => {
|
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 {
|
match *prop_decl {
|
||||||
PropertyDeclaration::AnimationTimingFunction(..) => true,
|
PropertyDeclaration::AnimationTimingFunction(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -151,11 +154,13 @@ pub struct KeyframesAnimation {
|
||||||
///
|
///
|
||||||
/// In practice, browsers seem to try to do their best job at it, so we might
|
/// 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.
|
/// want to go through all the actual keyframes and deduplicate properties.
|
||||||
|
#[allow(unsafe_code)]
|
||||||
fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> {
|
fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> {
|
||||||
let mut ret = vec![];
|
let mut ret = vec![];
|
||||||
// NB: declarations are already deduplicated, so we don't have to check for
|
// NB: declarations are already deduplicated, so we don't have to check for
|
||||||
// it here.
|
// 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) {
|
if let Some(property) = TransitionProperty::from_declaration(declaration) {
|
||||||
ret.push(property);
|
ret.push(property);
|
||||||
}
|
}
|
||||||
|
@ -266,10 +271,10 @@ impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
|
||||||
}
|
}
|
||||||
Ok(Arc::new(Keyframe {
|
Ok(Arc::new(Keyframe {
|
||||||
selector: prelude,
|
selector: prelude,
|
||||||
block: Arc::new(PropertyDeclarationBlock {
|
block: Arc::new(DOMRefCell::new(PropertyDeclarationBlock {
|
||||||
declarations: declarations,
|
declarations: declarations,
|
||||||
important_count: 0,
|
important_count: 0,
|
||||||
}),
|
})),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ use sink::ForgetfulSink;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
||||||
|
use std::ops::Deref;
|
||||||
use std::slice::IterMut;
|
use std::slice::IterMut;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
|
@ -139,7 +140,7 @@ impl<'a> Hash for ApplicableDeclarationsCacheQuery<'a> {
|
||||||
for declaration in self.declarations {
|
for declaration in self.declarations {
|
||||||
// Each declaration contians an Arc, which is a stable
|
// Each declaration contians an Arc, which is a stable
|
||||||
// pointer; we use that for hashing and equality.
|
// 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);
|
ptr.hash(state);
|
||||||
declaration.importance.hash(state);
|
declaration.importance.hash(state);
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,6 +311,10 @@ impl PropertyDeclarationBlock {
|
||||||
pub fn any_normal(&self) -> bool {
|
pub fn any_normal(&self) -> bool {
|
||||||
self.declarations.len() > self.important_count as usize
|
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 {
|
impl ToCss for PropertyDeclarationBlock {
|
||||||
|
@ -741,7 +745,7 @@ impl Shorthand {
|
||||||
|
|
||||||
/// Serializes possible shorthand value to String.
|
/// Serializes possible shorthand value to String.
|
||||||
pub fn serialize_shorthand_value_to_string<'a, I>(self, declarations: I, importance: Importance) -> 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 appendable_value = self.get_shorthand_appendable_value(declarations).unwrap();
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
append_declaration_value(&mut result, appendable_value, importance).unwrap();
|
append_declaration_value(&mut result, appendable_value, importance).unwrap();
|
||||||
|
@ -755,7 +759,7 @@ impl Shorthand {
|
||||||
declarations: I,
|
declarations: I,
|
||||||
is_first_serialization: &mut bool)
|
is_first_serialization: &mut bool)
|
||||||
-> Result<bool, fmt::Error>
|
-> 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) {
|
match self.get_shorthand_appendable_value(declarations) {
|
||||||
None => Ok(false),
|
None => Ok(false),
|
||||||
Some(appendable_value) => {
|
Some(appendable_value) => {
|
||||||
|
@ -772,8 +776,10 @@ impl Shorthand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_shorthand_appendable_value<'a, I>(self, declarations: I) -> Option<AppendableValue<'a, I>>
|
fn get_shorthand_appendable_value<'a, I>(self, declarations: I)
|
||||||
where I: Iterator<Item=&'a PropertyDeclaration> + Clone {
|
-> 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.
|
// Only cloning iterators (a few pointers each) not declarations.
|
||||||
let mut declarations2 = declarations.clone();
|
let mut declarations2 = declarations.clone();
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
//! Selector matching.
|
//! Selector matching.
|
||||||
|
|
||||||
use dom::PresentationalHintsSynthetizer;
|
use dom::PresentationalHintsSynthetizer;
|
||||||
|
use domrefcell::DOMRefCell;
|
||||||
use element_state::*;
|
use element_state::*;
|
||||||
use error_reporting::StdoutErrorReporter;
|
use error_reporting::StdoutErrorReporter;
|
||||||
use keyframes::KeyframesAnimation;
|
use keyframes::KeyframesAnimation;
|
||||||
|
@ -178,7 +179,7 @@ impl Stylist {
|
||||||
|
|
||||||
map.insert(Rule {
|
map.insert(Rule {
|
||||||
selector: selector.complex_selector.clone(),
|
selector: selector.complex_selector.clone(),
|
||||||
declarations: style_rule.declarations.clone(),
|
declarations: style_rule.block.clone(),
|
||||||
specificity: selector.specificity,
|
specificity: selector.specificity,
|
||||||
source_order: rules_source_order,
|
source_order: rules_source_order,
|
||||||
});
|
});
|
||||||
|
@ -327,11 +328,12 @@ impl Stylist {
|
||||||
/// that is, whether the matched selectors are simple enough to allow the
|
/// that is, whether the matched selectors are simple enough to allow the
|
||||||
/// matching logic to be reduced to the logic in
|
/// matching logic to be reduced to the logic in
|
||||||
/// `css::matching::PrivateMatchMethods::candidate_element_allows_for_style_sharing`.
|
/// `css::matching::PrivateMatchMethods::candidate_element_allows_for_style_sharing`.
|
||||||
|
#[allow(unsafe_code)]
|
||||||
pub fn push_applicable_declarations<E, V>(
|
pub fn push_applicable_declarations<E, V>(
|
||||||
&self,
|
&self,
|
||||||
element: &E,
|
element: &E,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
style_attribute: Option<&Arc<PropertyDeclarationBlock>>,
|
style_attribute: Option<&Arc<DOMRefCell<PropertyDeclarationBlock>>>,
|
||||||
pseudo_element: Option<&PseudoElement>,
|
pseudo_element: Option<&PseudoElement>,
|
||||||
applicable_declarations: &mut V,
|
applicable_declarations: &mut V,
|
||||||
reason: MatchingReason) -> StyleRelations
|
reason: MatchingReason) -> StyleRelations
|
||||||
|
@ -390,8 +392,9 @@ impl Stylist {
|
||||||
debug!("author normal: {:?}", relations);
|
debug!("author normal: {:?}", relations);
|
||||||
|
|
||||||
// Step 4: Normal style attributes.
|
// Step 4: Normal style attributes.
|
||||||
if let Some(sa) = style_attribute {
|
if let Some(sa) = style_attribute {
|
||||||
if sa.any_normal() {
|
// FIXME: Is this thread-safe?
|
||||||
|
if unsafe { sa.borrow_for_layout() }.any_normal() {
|
||||||
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
|
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
|
||||||
Push::push(
|
Push::push(
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
|
@ -413,7 +416,8 @@ impl Stylist {
|
||||||
|
|
||||||
// Step 6: `!important` style attributes.
|
// Step 6: `!important` style attributes.
|
||||||
if let Some(sa) = style_attribute {
|
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;
|
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
|
||||||
Push::push(
|
Push::push(
|
||||||
applicable_declarations,
|
applicable_declarations,
|
||||||
|
@ -691,6 +695,7 @@ impl SelectorMap {
|
||||||
|
|
||||||
/// Append to `rule_list` all universal Rules (rules with selector `*|*`) in
|
/// Append to `rule_list` all universal Rules (rules with selector `*|*`) in
|
||||||
/// `self` sorted by specifity and source order.
|
/// `self` sorted by specifity and source order.
|
||||||
|
#[allow(unsafe_code)]
|
||||||
pub fn get_universal_rules<V>(&self,
|
pub fn get_universal_rules<V>(&self,
|
||||||
matching_rules_list: &mut V)
|
matching_rules_list: &mut V)
|
||||||
where V: VecLike<ApplicableDeclarationBlock>
|
where V: VecLike<ApplicableDeclarationBlock>
|
||||||
|
@ -704,11 +709,13 @@ impl SelectorMap {
|
||||||
for rule in self.other_rules.iter() {
|
for rule in self.other_rules.iter() {
|
||||||
if rule.selector.compound_selector.is_empty() &&
|
if rule.selector.compound_selector.is_empty() &&
|
||||||
rule.selector.next.is_none() {
|
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(
|
matching_rules_list.push(
|
||||||
rule.to_applicable_declaration_block(Importance::Normal));
|
rule.to_applicable_declaration_block(Importance::Normal));
|
||||||
}
|
}
|
||||||
if rule.declarations.any_important() {
|
if block.any_important() {
|
||||||
matching_rules_list.push(
|
matching_rules_list.push(
|
||||||
rule.to_applicable_declaration_block(Importance::Important));
|
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.
|
/// Adds rules in `rules` that match `element` to the `matching_rules` list.
|
||||||
|
#[allow(unsafe_code)]
|
||||||
fn get_matching_rules<E, V>(element: &E,
|
fn get_matching_rules<E, V>(element: &E,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
rules: &[Rule],
|
rules: &[Rule],
|
||||||
|
@ -756,7 +764,8 @@ impl SelectorMap {
|
||||||
V: VecLike<ApplicableDeclarationBlock>
|
V: VecLike<ApplicableDeclarationBlock>
|
||||||
{
|
{
|
||||||
for rule in rules.iter() {
|
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() {
|
let any_declaration_for_importance = if importance.important() {
|
||||||
block.any_important()
|
block.any_important()
|
||||||
} else {
|
} else {
|
||||||
|
@ -844,7 +853,7 @@ pub struct Rule {
|
||||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||||
pub selector: Arc<ComplexSelector<TheSelectorImpl>>,
|
pub selector: Arc<ComplexSelector<TheSelectorImpl>>,
|
||||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||||
pub declarations: Arc<PropertyDeclarationBlock>,
|
pub declarations: Arc<DOMRefCell<PropertyDeclarationBlock>>,
|
||||||
pub source_order: usize,
|
pub source_order: usize,
|
||||||
pub specificity: u32,
|
pub specificity: u32,
|
||||||
}
|
}
|
||||||
|
@ -869,7 +878,7 @@ pub struct ApplicableDeclarationBlock {
|
||||||
/// Contains declarations of either importance, but only those of self.importance are relevant.
|
/// Contains declarations of either importance, but only those of self.importance are relevant.
|
||||||
/// Use ApplicableDeclarationBlock::iter
|
/// Use ApplicableDeclarationBlock::iter
|
||||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||||
pub mixed_declarations: Arc<PropertyDeclarationBlock>,
|
pub mixed_declarations: Arc<DOMRefCell<PropertyDeclarationBlock>>,
|
||||||
pub importance: Importance,
|
pub importance: Importance,
|
||||||
pub source_order: usize,
|
pub source_order: usize,
|
||||||
pub specificity: u32,
|
pub specificity: u32,
|
||||||
|
@ -877,7 +886,7 @@ pub struct ApplicableDeclarationBlock {
|
||||||
|
|
||||||
impl ApplicableDeclarationBlock {
|
impl ApplicableDeclarationBlock {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_declarations(declarations: Arc<PropertyDeclarationBlock>,
|
pub fn from_declarations(declarations: Arc<DOMRefCell<PropertyDeclarationBlock>>,
|
||||||
importance: Importance)
|
importance: Importance)
|
||||||
-> Self {
|
-> Self {
|
||||||
ApplicableDeclarationBlock {
|
ApplicableDeclarationBlock {
|
||||||
|
@ -888,9 +897,11 @@ impl ApplicableDeclarationBlock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
pub fn iter(&self) -> ApplicableDeclarationBlockIter {
|
pub fn iter(&self) -> ApplicableDeclarationBlockIter {
|
||||||
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,
|
importance: self.importance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, decode_stylesheet_bytes};
|
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, decode_stylesheet_bytes};
|
||||||
use cssparser::{AtRuleType, RuleListParser, Token};
|
use cssparser::{AtRuleType, RuleListParser, Token};
|
||||||
|
use domrefcell::DOMRefCell;
|
||||||
use encoding::EncodingRef;
|
use encoding::EncodingRef;
|
||||||
use error_reporting::ParseErrorReporter;
|
use error_reporting::ParseErrorReporter;
|
||||||
use font_face::{FontFaceRule, parse_font_face_block};
|
use font_face::{FontFaceRule, parse_font_face_block};
|
||||||
|
@ -106,7 +107,7 @@ impl MediaRule {
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct StyleRule {
|
pub struct StyleRule {
|
||||||
pub selectors: Vec<Selector<TheSelectorImpl>>,
|
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, ()> {
|
-> Result<CSSRule, ()> {
|
||||||
Ok(CSSRule::Style(Arc::new(StyleRule {
|
Ok(CSSRule::Style(Arc::new(StyleRule {
|
||||||
selectors: prelude,
|
selectors: prelude,
|
||||||
declarations: Arc::new(parse_property_declaration_list(self.context, input))
|
block: Arc::new(DOMRefCell::new(parse_property_declaration_list(self.context, input)))
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
|
||||||
use style::arc_ptr_eq;
|
use style::arc_ptr_eq;
|
||||||
use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext};
|
use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext};
|
||||||
use style::dom::{NodeInfo, TDocument, TElement, TNode};
|
use style::dom::{NodeInfo, TDocument, TElement, TNode};
|
||||||
|
use style::domrefcell::DOMRefCell;
|
||||||
use style::error_reporting::StdoutErrorReporter;
|
use style::error_reporting::StdoutErrorReporter;
|
||||||
use style::gecko::data::{NUM_THREADS, PerDocumentStyleData};
|
use style::gecko::data::{NUM_THREADS, PerDocumentStyleData};
|
||||||
use style::gecko::selector_impl::{GeckoSelectorImpl, PseudoElement};
|
use style::gecko::selector_impl::{GeckoSelectorImpl, PseudoElement};
|
||||||
|
@ -344,7 +345,9 @@ pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
|
||||||
-> ServoDeclarationBlockStrong {
|
-> ServoDeclarationBlockStrong {
|
||||||
let value = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) };
|
let value = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) };
|
||||||
Arc::new(GeckoDeclarationBlock {
|
Arc::new(GeckoDeclarationBlock {
|
||||||
declarations: GeckoElement::parse_style_attribute(value).map(Arc::new),
|
declarations: GeckoElement::parse_style_attribute(value).map(|block| {
|
||||||
|
Arc::new(DOMRefCell::new(block))
|
||||||
|
}),
|
||||||
cache: AtomicPtr::new(cache),
|
cache: AtomicPtr::new(cache),
|
||||||
immutable: AtomicBool::new(false),
|
immutable: AtomicBool::new(false),
|
||||||
}).into_strong()
|
}).into_strong()
|
||||||
|
|
|
@ -6,9 +6,11 @@ use cssparser::Parser;
|
||||||
use selectors::parser::{LocalName, ParserContext, parse_selector_list};
|
use selectors::parser::{LocalName, ParserContext, parse_selector_list};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
|
use style::domrefcell::DOMRefCell;
|
||||||
use style::properties::{PropertyDeclarationBlock, PropertyDeclaration, DeclaredValue};
|
use style::properties::{PropertyDeclarationBlock, PropertyDeclaration, DeclaredValue};
|
||||||
use style::properties::{longhands, Importance};
|
use style::properties::{longhands, Importance};
|
||||||
use style::selector_matching::{Rule, SelectorMap};
|
use style::selector_matching::{Rule, SelectorMap};
|
||||||
|
use style::thread_state;
|
||||||
|
|
||||||
/// Helper method to get some Rules from selector strings.
|
/// Helper method to get some Rules from selector strings.
|
||||||
/// Each sublist of the result contains the Rules for one StyleRule.
|
/// Each sublist of the result contains the Rules for one StyleRule.
|
||||||
|
@ -19,14 +21,14 @@ fn get_mock_rules(css_selectors: &[&str]) -> Vec<Vec<Rule>> {
|
||||||
.unwrap().into_iter().map(|s| {
|
.unwrap().into_iter().map(|s| {
|
||||||
Rule {
|
Rule {
|
||||||
selector: s.complex_selector.clone(),
|
selector: s.complex_selector.clone(),
|
||||||
declarations: Arc::new(PropertyDeclarationBlock {
|
declarations: Arc::new(DOMRefCell::new(PropertyDeclarationBlock {
|
||||||
declarations: vec![
|
declarations: vec![
|
||||||
(PropertyDeclaration::Display(DeclaredValue::Value(
|
(PropertyDeclaration::Display(DeclaredValue::Value(
|
||||||
longhands::display::SpecifiedValue::block)),
|
longhands::display::SpecifiedValue::block)),
|
||||||
Importance::Normal),
|
Importance::Normal),
|
||||||
],
|
],
|
||||||
important_count: 0,
|
important_count: 0,
|
||||||
}),
|
})),
|
||||||
specificity: s.specificity,
|
specificity: s.specificity,
|
||||||
source_order: i,
|
source_order: i,
|
||||||
}
|
}
|
||||||
|
@ -99,6 +101,7 @@ fn test_insert() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_universal_rules() {
|
fn test_get_universal_rules() {
|
||||||
|
thread_state::initialize(thread_state::LAYOUT);
|
||||||
let map = get_mock_map(&["*|*", "#foo > *|*", ".klass", "#id"]);
|
let map = get_mock_map(&["*|*", "#foo > *|*", ".klass", "#id"]);
|
||||||
let mut decls = vec![];
|
let mut decls = vec![];
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ use std::borrow::ToOwned;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use string_cache::{Atom, Namespace as NsAtom};
|
use string_cache::{Atom, Namespace as NsAtom};
|
||||||
|
use style::domrefcell::DOMRefCell;
|
||||||
use style::error_reporting::ParseErrorReporter;
|
use style::error_reporting::ParseErrorReporter;
|
||||||
use style::keyframes::{Keyframe, KeyframeSelector, KeyframePercentage};
|
use style::keyframes::{Keyframe, KeyframeSelector, KeyframePercentage};
|
||||||
use style::parser::ParserContextExtraData;
|
use style::parser::ParserContextExtraData;
|
||||||
|
@ -97,7 +98,7 @@ fn test_parse_stylesheet() {
|
||||||
specificity: (0 << 20) + (1 << 10) + (1 << 0),
|
specificity: (0 << 20) + (1 << 10) + (1 << 0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
declarations: Arc::new(PropertyDeclarationBlock {
|
block: Arc::new(DOMRefCell::new(PropertyDeclarationBlock {
|
||||||
declarations: vec![
|
declarations: vec![
|
||||||
(PropertyDeclaration::Display(DeclaredValue::Value(
|
(PropertyDeclaration::Display(DeclaredValue::Value(
|
||||||
longhands::display::SpecifiedValue::none)),
|
longhands::display::SpecifiedValue::none)),
|
||||||
|
@ -106,7 +107,7 @@ fn test_parse_stylesheet() {
|
||||||
Importance::Important),
|
Importance::Important),
|
||||||
],
|
],
|
||||||
important_count: 2,
|
important_count: 2,
|
||||||
}),
|
})),
|
||||||
})),
|
})),
|
||||||
CSSRule::Style(Arc::new(StyleRule {
|
CSSRule::Style(Arc::new(StyleRule {
|
||||||
selectors: vec![
|
selectors: vec![
|
||||||
|
@ -145,14 +146,14 @@ fn test_parse_stylesheet() {
|
||||||
specificity: (0 << 20) + (0 << 10) + (1 << 0),
|
specificity: (0 << 20) + (0 << 10) + (1 << 0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
declarations: Arc::new(PropertyDeclarationBlock {
|
block: Arc::new(DOMRefCell::new(PropertyDeclarationBlock {
|
||||||
declarations: vec![
|
declarations: vec![
|
||||||
(PropertyDeclaration::Display(DeclaredValue::Value(
|
(PropertyDeclaration::Display(DeclaredValue::Value(
|
||||||
longhands::display::SpecifiedValue::block)),
|
longhands::display::SpecifiedValue::block)),
|
||||||
Importance::Normal),
|
Importance::Normal),
|
||||||
],
|
],
|
||||||
important_count: 0,
|
important_count: 0,
|
||||||
}),
|
})),
|
||||||
})),
|
})),
|
||||||
CSSRule::Style(Arc::new(StyleRule {
|
CSSRule::Style(Arc::new(StyleRule {
|
||||||
selectors: vec![
|
selectors: vec![
|
||||||
|
@ -180,7 +181,7 @@ fn test_parse_stylesheet() {
|
||||||
specificity: (1 << 20) + (1 << 10) + (0 << 0),
|
specificity: (1 << 20) + (1 << 10) + (0 << 0),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
declarations: Arc::new(PropertyDeclarationBlock {
|
block: Arc::new(DOMRefCell::new(PropertyDeclarationBlock {
|
||||||
declarations: vec![
|
declarations: vec![
|
||||||
(PropertyDeclaration::BackgroundColor(DeclaredValue::Value(
|
(PropertyDeclaration::BackgroundColor(DeclaredValue::Value(
|
||||||
longhands::background_color::SpecifiedValue {
|
longhands::background_color::SpecifiedValue {
|
||||||
|
@ -228,7 +229,7 @@ fn test_parse_stylesheet() {
|
||||||
Importance::Normal),
|
Importance::Normal),
|
||||||
],
|
],
|
||||||
important_count: 0,
|
important_count: 0,
|
||||||
}),
|
})),
|
||||||
})),
|
})),
|
||||||
CSSRule::Keyframes(Arc::new(KeyframesRule {
|
CSSRule::Keyframes(Arc::new(KeyframesRule {
|
||||||
name: "foo".into(),
|
name: "foo".into(),
|
||||||
|
@ -236,19 +237,19 @@ fn test_parse_stylesheet() {
|
||||||
Arc::new(Keyframe {
|
Arc::new(Keyframe {
|
||||||
selector: KeyframeSelector::new_for_unit_testing(
|
selector: KeyframeSelector::new_for_unit_testing(
|
||||||
vec![KeyframePercentage::new(0.)]),
|
vec![KeyframePercentage::new(0.)]),
|
||||||
block: Arc::new(PropertyDeclarationBlock {
|
block: Arc::new(DOMRefCell::new(PropertyDeclarationBlock {
|
||||||
declarations: vec![
|
declarations: vec![
|
||||||
(PropertyDeclaration::Width(DeclaredValue::Value(
|
(PropertyDeclaration::Width(DeclaredValue::Value(
|
||||||
LengthOrPercentageOrAuto::Percentage(Percentage(0.)))),
|
LengthOrPercentageOrAuto::Percentage(Percentage(0.)))),
|
||||||
Importance::Normal),
|
Importance::Normal),
|
||||||
],
|
],
|
||||||
important_count: 0,
|
important_count: 0,
|
||||||
})
|
}))
|
||||||
}),
|
}),
|
||||||
Arc::new(Keyframe {
|
Arc::new(Keyframe {
|
||||||
selector: KeyframeSelector::new_for_unit_testing(
|
selector: KeyframeSelector::new_for_unit_testing(
|
||||||
vec![KeyframePercentage::new(1.)]),
|
vec![KeyframePercentage::new(1.)]),
|
||||||
block: Arc::new(PropertyDeclarationBlock {
|
block: Arc::new(DOMRefCell::new(PropertyDeclarationBlock {
|
||||||
declarations: vec![
|
declarations: vec![
|
||||||
(PropertyDeclaration::Width(DeclaredValue::Value(
|
(PropertyDeclaration::Width(DeclaredValue::Value(
|
||||||
LengthOrPercentageOrAuto::Percentage(Percentage(1.)))),
|
LengthOrPercentageOrAuto::Percentage(Percentage(1.)))),
|
||||||
|
@ -259,7 +260,7 @@ fn test_parse_stylesheet() {
|
||||||
Importance::Normal),
|
Importance::Normal),
|
||||||
],
|
],
|
||||||
important_count: 0,
|
important_count: 0,
|
||||||
}),
|
})),
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
}))
|
}))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue