Skip to content
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

style: Split style resolution and dynamic change computation. #17688

Merged
merged 11 commits into from Jul 12, 2017
@@ -37,7 +37,7 @@ use style::selector_parser::PseudoElement;
use style_traits::ToCss;
use style_traits::cursor::Cursor;
use webrender_traits::ClipId;
use wrapper::{LayoutNodeHelpers, LayoutNodeLayoutData};
use wrapper::LayoutNodeLayoutData;

/// Mutable data belonging to the LayoutThread.
///
@@ -680,7 +680,9 @@ pub fn process_resolved_style_request<'a, N>(context: &LayoutContext,
layout_root: &mut Flow) -> String
where N: LayoutNode,
{
use style::stylist::RuleInclusion;
use style::traversal::resolve_style;

let element = node.as_element().unwrap();

// We call process_resolved_style_request after performing a whole-document
@@ -689,30 +691,43 @@ pub fn process_resolved_style_request<'a, N>(context: &LayoutContext,
return process_resolved_style_request_internal(node, pseudo, property, layout_root);
}

// However, the element may be in a display:none subtree. The style system
// has a mechanism to give us that within a defined scope (after which point
// it's cleared to maintained style system invariants).
// In a display: none subtree. No pseudo-element exists.
if pseudo.is_some() {
return String::new();
}

let mut tlc = ThreadLocalStyleContext::new(&context.style_context);
let mut context = StyleContext {
shared: &context.style_context,
thread_local: &mut tlc,
};
let mut result = None;
let ensure = |el: N::ConcreteElement| el.as_node().initialize_data();
let clear = |el: N::ConcreteElement| el.as_node().clear_data();
resolve_style(&mut context, element, &ensure, &clear, |_: &_| {
let s = process_resolved_style_request_internal(node, pseudo, property, layout_root);
result = Some(s);
});
result.unwrap()

let styles = resolve_style(&mut context, element, RuleInclusion::All);
let style = styles.primary();
let longhand_id = match *property {
PropertyId::Longhand(id) => id,
// Firefox returns blank strings for the computed value of shorthands,
// so this should be web-compatible.
PropertyId::Shorthand(_) => return String::new(),
PropertyId::Custom(ref name) => {
return style.computed_value_to_string(PropertyDeclarationId::Custom(name))
}
};

// No need to care about used values here, since we're on a display: none
// subtree, use the resolved value.
style.computed_value_to_string(PropertyDeclarationId::Longhand(longhand_id))
}

/// The primary resolution logic, which assumes that the element is styled.
fn process_resolved_style_request_internal<'a, N>(requested_node: N,
pseudo: &Option<PseudoElement>,
property: &PropertyId,
layout_root: &mut Flow) -> String
where N: LayoutNode,
fn process_resolved_style_request_internal<'a, N>(
requested_node: N,
pseudo: &Option<PseudoElement>,
property: &PropertyId,
layout_root: &mut Flow,
) -> String
where
N: LayoutNode,
{
let layout_el = requested_node.to_threadsafe().as_element().unwrap();
let layout_el = match *pseudo {
@@ -721,6 +736,8 @@ fn process_resolved_style_request_internal<'a, N>(requested_node: N,
Some(PseudoElement::DetailsSummary) |
Some(PseudoElement::DetailsContent) |
Some(PseudoElement::Selection) => None,
// FIXME(emilio): What about the other pseudos? Probably they shouldn't
// just return the element's style!
_ => Some(layout_el)
};

@@ -735,7 +752,6 @@ fn process_resolved_style_request_internal<'a, N>(requested_node: N,
};

let style = &*layout_el.resolved_style();

let longhand_id = match *property {
PropertyId::Longhand(id) => id,

@@ -5,21 +5,6 @@
use attr::CaseSensitivity;
use bloom::BloomFilter;

bitflags! {
/// Set of flags that determine the different kind of elements affected by
/// the selector matching process.
///
/// This is used to implement efficient sharing.
#[derive(Default)]
pub flags StyleRelations: usize {
/// Whether this element is affected by presentational hints. This is
/// computed externally (that is, in Servo).
const AFFECTED_BY_PRESENTATIONAL_HINTS = 1 << 0,
/// Whether this element has pseudo-element styles. Computed externally.
const AFFECTED_BY_PSEUDO_ELEMENTS = 1 << 1,
}
}

/// What kind of selector matching mode we should use.
///
/// There are two modes of selector matching. The difference is only noticeable
@@ -89,9 +74,6 @@ impl QuirksMode {
/// transient data that applies to only a single selector.
#[derive(Clone)]
pub struct MatchingContext<'a> {
/// Output that records certains relations between elements noticed during
/// matching (and also extended after matching).
pub relations: StyleRelations,
/// Input with the matching mode we should use when matching selectors.
pub matching_mode: MatchingMode,
/// Input with the bloom filter used to fast-reject selectors.
@@ -116,7 +98,6 @@ impl<'a> MatchingContext<'a> {
-> Self
{
Self {
relations: StyleRelations::empty(),
matching_mode: matching_mode,
bloom_filter: bloom_filter,
visited_handling: VisitedHandlingMode::AllLinksUnvisited,
@@ -134,7 +115,6 @@ impl<'a> MatchingContext<'a> {
-> Self
{
Self {
relations: StyleRelations::empty(),
matching_mode: matching_mode,
bloom_filter: bloom_filter,
visited_handling: visited_handling,
@@ -714,8 +714,6 @@ fn matches_simple_selector<E, F>(
matches_last_child(element, flags_setter)
}
Component::Root => {
// We never share styles with an element with no parent, so no point
// in creating a new StyleRelation.
element.is_root()
}
Component::Empty => {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.