New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rule tree, v1 #13202
Rule tree, v1 #13202
Changes from 1 commit
File filter...
Jump to…
Concurrent rule tree, v1
This patch introduces infrastructure for the rule tree, and constructs it. We don't use it yet, nor have good heuristics for GC'ing it, but this should not happen anymore once we store the rule node reference in the node. I haven't messed up with memory orders because I want to do a try run with it, then mess with them. Take down the ApplicableDeclarationsCache, use the rule tree for doing the cascade.
- Loading branch information
| @@ -7,6 +7,7 @@ | ||
| use Atom; | ||
| use bezier::Bezier; | ||
| use context::SharedStyleContext; | ||
| use declarations_iterators::RawDeclarationsIterator; | ||
| use dom::{OpaqueNode, UnsafeNode}; | ||
| use euclid::point::Point2D; | ||
| use keyframes::{KeyframesStep, KeyframesStepValue}; | ||
| @@ -17,7 +18,6 @@ use properties::longhands::animation_iteration_count::computed_value::AnimationI | ||
| use properties::longhands::animation_play_state::computed_value::AnimationPlayState; | ||
| use properties::longhands::transition_timing_function::computed_value::StartEnd; | ||
| use properties::longhands::transition_timing_function::computed_value::TransitionTimingFunction; | ||
| use selector_matching::ApplicableDeclarationBlock; | ||
| use std::sync::Arc; | ||
| use std::sync::mpsc::Sender; | ||
| use timer::Timer; | ||
| @@ -385,23 +385,24 @@ fn compute_style_for_animation_step(context: &SharedStyleContext, | ||
| style_from_cascade: &ComputedValues) | ||
| -> ComputedValues { | ||
| match step.value { | ||
| // TODO: avoiding this spurious clone might involve having to create | ||
| // an Arc in the below (more common case). | ||
| KeyframesStepValue::ComputedValues => style_from_cascade.clone(), | ||
| KeyframesStepValue::Declarations { block: ref declarations } => { | ||
| let declaration_block = ApplicableDeclarationBlock { | ||
| mixed_declarations: declarations.clone(), | ||
| importance: Importance::Normal, | ||
| source_order: 0, | ||
| specificity: ::std::u32::MAX, | ||
| }; | ||
| let (computed, _) = properties::cascade(context.viewport_size, | ||
| &[declaration_block], | ||
| Some(previous_style), | ||
| None, | ||
| None, | ||
| context.error_reporter.clone(), | ||
| CascadeFlags::empty()); | ||
| let guard = declarations.read(); | ||
|
|
||
| // No !important in keyframes. | ||
| debug_assert!(guard.declarations.iter() | ||
| .all(|&(_, importance)| importance == Importance::Normal)); | ||
|
|
||
| let iter = RawDeclarationsIterator::new(&guard.declarations); | ||
emilio
Author
Member
|
||
|
|
||
| let computed = | ||
| properties::apply_declarations(context.viewport_size, | ||
| /* is_root = */ false, | ||
| iter, | ||
| previous_style, | ||
| /* cascade_info = */ None, | ||
| context.error_reporter.clone(), | ||
| CascadeFlags::empty()); | ||
| computed | ||
| } | ||
| } | ||
| @@ -5,14 +5,15 @@ | ||
| //! Per-node data used in style calculation. | ||
|
|
||
| use properties::ComputedValues; | ||
| use rule_tree::StrongRuleNode; | ||
| use selector_impl::PseudoElement; | ||
| use std::collections::HashMap; | ||
| use std::hash::BuildHasherDefault; | ||
| use std::mem; | ||
| use std::ops::{Deref, DerefMut}; | ||
| use std::sync::Arc; | ||
|
|
||
| type PseudoStylesInner = HashMap<PseudoElement, Arc<ComputedValues>, | ||
| type PseudoStylesInner = HashMap<PseudoElement, (Arc<ComputedValues>, StrongRuleNode), | ||
| BuildHasherDefault<::fnv::FnvHasher>>; | ||
| #[derive(Clone, Debug)] | ||
| pub struct PseudoStyles(PseudoStylesInner); | ||
| @@ -39,14 +40,18 @@ pub struct ElementStyles { | ||
| /// The results of CSS styling for this node. | ||
| pub primary: Arc<ComputedValues>, | ||
|
|
||
| /// The rule node representing the last rule matched for this node. | ||
| pub rule_node: StrongRuleNode, | ||
bholley
Contributor
|
||
|
|
||
| /// The results of CSS styling for each pseudo-element (if any). | ||
| pub pseudos: PseudoStyles, | ||
| } | ||
|
|
||
| impl ElementStyles { | ||
| pub fn new(primary: Arc<ComputedValues>) -> Self { | ||
| pub fn new(primary: Arc<ComputedValues>, rule_node: StrongRuleNode) -> Self { | ||
| ElementStyles { | ||
| primary: primary, | ||
| rule_node: rule_node, | ||
| pseudos: PseudoStyles::empty(), | ||
| } | ||
| } | ||
| @@ -185,11 +190,6 @@ impl ElementData { | ||
| } | ||
| } | ||
|
|
||
| pub fn style_text_node(&mut self, style: Arc<ComputedValues>) { | ||
| self.styles = ElementDataStyles::Current(ElementStyles::new(style)); | ||
| self.restyle_data = None; | ||
| } | ||
|
|
||
| pub fn finish_styling(&mut self, styles: ElementStyles) { | ||
| debug_assert!(self.styles.is_previous()); | ||
| self.styles = ElementDataStyles::Current(styles); | ||
| @@ -0,0 +1,83 @@ | ||
| /* 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/. */ | ||
|
|
||
| //! A set of simple iterators to be reused for doing the cascade. | ||
|
|
||
| use properties::{Importance, PropertyDeclaration}; | ||
|
|
||
|
|
||
| /// An iterator that applies the declarations in a list that matches the given | ||
| /// importance. | ||
| #[derive(Clone)] | ||
| pub struct SimpleDeclarationsIterator<'a> { | ||
| declarations: &'a [(PropertyDeclaration, Importance)], | ||
| importance: Importance, | ||
| index: usize, | ||
| } | ||
|
|
||
| impl<'a> SimpleDeclarationsIterator<'a> { | ||
| pub fn new(declarations: &'a [(PropertyDeclaration, Importance)], | ||
| importance: Importance) -> Self { | ||
| SimpleDeclarationsIterator { | ||
| declarations: declarations, | ||
| importance: importance, | ||
| index: 0, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl<'a> Iterator for SimpleDeclarationsIterator<'a> { | ||
| type Item = &'a PropertyDeclaration; | ||
|
|
||
| fn next(&mut self) -> Option<Self::Item> { | ||
| loop { | ||
| if self.index == self.declarations.len() { | ||
| return None; | ||
| } | ||
|
|
||
| let (ref decl, importance) = | ||
| self.declarations[self.declarations.len() - self.index - 1]; | ||
|
|
||
| self.index += 1; | ||
|
|
||
| if importance == self.importance { | ||
| return Some(decl) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// An iterator that applies the declarations in a list without checking any | ||
| /// order. | ||
| #[derive(Clone)] | ||
| pub struct RawDeclarationsIterator<'a> { | ||
| declarations: &'a [(PropertyDeclaration, Importance)], | ||
| index: usize, | ||
| } | ||
|
|
||
| impl<'a> RawDeclarationsIterator<'a> { | ||
| pub fn new(declarations: &'a [(PropertyDeclaration, Importance)]) -> Self { | ||
| RawDeclarationsIterator { | ||
| declarations: declarations, | ||
| index: 0, | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl<'a> Iterator for RawDeclarationsIterator<'a> { | ||
| type Item = &'a PropertyDeclaration; | ||
|
|
||
| fn next(&mut self) -> Option<Self::Item> { | ||
| if self.index == self.declarations.len() { | ||
| return None; | ||
| } | ||
|
|
||
| let (ref decl, _) = | ||
| self.declarations[self.declarations.len() - self.index - 1]; | ||
|
|
||
| self.index += 1; | ||
|
|
||
| return Some(decl) | ||
| } | ||
| } |
Isn’t max specificity here important?