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

incremental restyle: Hoist more stuff to Element #13951

Merged
merged 1 commit into from Oct 28, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -62,7 +62,7 @@ use text::TextRunScanner;
use traversal::PostorderNodeMutTraversal;
use url::Url;
use util::opts;
use wrapper::{TextContent, ThreadSafeLayoutNodeHelpers};
use wrapper::{LayoutNodeLayoutData, TextContent, ThreadSafeLayoutNodeHelpers};

/// The results of flow construction for a DOM node.
#[derive(Clone)]
@@ -221,7 +221,7 @@ impl InlineFragmentsAccumulator {
address: node.opaque(),
pseudo: node.get_pseudo_element_type().strip(),
style: node.style(style_context),
selected_style: node.selected_style(style_context),
selected_style: node.selected_style(),
flags: InlineFragmentNodeFlags::empty(),
}),
bidi_control_chars: None,
@@ -514,11 +514,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
box UnscannedTextFragmentInfo::new(" ".to_owned(), None));
properties::modify_style_for_replaced_content(&mut whitespace_style);
properties::modify_style_for_text(&mut whitespace_style);
let style_context = self.style_context();
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
whitespace_style,
node.selected_style(style_context),
node.selected_style(),
whitespace_damage,
fragment_info);
inline_fragment_accumulator.fragments.fragments.push_back(fragment);
@@ -650,7 +649,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
_ => properties::modify_style_for_text(&mut style)
}

let selected_style = node.selected_style(self.style_context());
let selected_style = node.selected_style();

match text_content {
TextContent::Text(string) => {
@@ -811,7 +810,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
whitespace_style,
node.selected_style(self.style_context()),
node.selected_style(),
whitespace_damage,
fragment_info);
fragment_accumulator.fragments.fragments.push_back(fragment)
@@ -834,7 +833,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
node.get_pseudo_element_type().strip(),
modified_style,
node.selected_style(self.style_context()),
node.selected_style(),
node.restyle_damage(),
info);
fragment_accumulator.fragments.fragments.push_back(fragment)
@@ -921,15 +920,14 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
_ => unreachable!()
};

let style_context = self.style_context();
let mut modified_style = node.style(self.style_context());
properties::modify_style_for_outer_inline_block_fragment(&mut modified_style);
let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(
block_flow));
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
node.get_pseudo_element_type().strip(),
modified_style,
node.selected_style(style_context),
node.selected_style(),
node.restyle_damage(),
fragment_info);

@@ -964,7 +962,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
PseudoElementType::Normal,
style,
node.selected_style(style_context),
node.selected_style(),
node.restyle_damage(),
fragment_info);

@@ -1076,7 +1074,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
Fragment::from_opaque_node_and_style(node.opaque(),
PseudoElementType::Normal,
wrapper_style,
node.selected_style(self.style_context()),
node.selected_style(),
node.restyle_damage(),
SpecificFragmentInfo::TableWrapper);
let wrapper_float_kind = FloatKind::from_property(float_value);
@@ -1661,7 +1659,7 @@ trait ObjectElement {

impl<N> ObjectElement for N where N: ThreadSafeLayoutNode {
fn has_object_data(&self) -> bool {
let elem = self.as_element();
let elem = self.as_element().unwrap();
let type_and_data = (elem.get_attr(&ns!(), &atom!("type")), elem.get_attr(&ns!(), &atom!("data")));
match type_and_data {
(None, Some(uri)) => is_image_data(uri),
@@ -1670,7 +1668,7 @@ impl<N> ObjectElement for N where N: ThreadSafeLayoutNode {
}

fn object_data(&self) -> Option<Url> {
let elem = self.as_element();
let elem = self.as_element().unwrap();
let type_and_data = (elem.get_attr(&ns!(), &atom!("type")), elem.get_attr(&ns!(), &atom!("data")));
match type_and_data {
(None, Some(uri)) if is_image_data(uri) => Url::parse(uri).ok(),
@@ -885,7 +885,7 @@ pub struct TableColumnFragmentInfo {
impl TableColumnFragmentInfo {
/// Create the information specific to an table column fragment.
pub fn new<N: ThreadSafeLayoutNode>(node: &N) -> TableColumnFragmentInfo {
let element = node.as_element();
let element = node.as_element().unwrap();
let span = element.get_attr(&ns!(), &atom!("span"))
.and_then(|string| string.parse().ok())
.unwrap_or(0);
@@ -908,7 +908,7 @@ impl Fragment {
Fragment {
node: node.opaque(),
style: style,
selected_style: node.selected_style(style_context),
selected_style: node.selected_style(),
restyle_damage: restyle_damage,
border_box: LogicalRect::zero(writing_mode),
border_padding: LogicalMargin::zero(writing_mode),
@@ -19,7 +19,7 @@ use script_layout_interface::rpc::{HitTestResponse, LayoutRPC};
use script_layout_interface::rpc::{MarginStyleResponse, NodeGeometryResponse};
use script_layout_interface::rpc::{NodeOverflowResponse, OffsetParentResponse};
use script_layout_interface::rpc::ResolvedStyleResponse;
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use script_traits::LayoutMsg as ConstellationMsg;
use script_traits::UntrustedNodeAddress;
use sequential;
@@ -36,7 +36,7 @@ use style::selector_impl::PseudoElement;
use style::selector_matching::Stylist;
use style::values::LocalToCss;
use style_traits::cursor::Cursor;
use wrapper::{LayoutNodeLayoutData, ThreadSafeLayoutNodeHelpers};
use wrapper::{LayoutNodeHelpers, LayoutNodeLayoutData};

/// Mutable data belonging to the LayoutThread.
///
@@ -640,27 +640,27 @@ pub fn process_resolved_style_request<'a, N, C>(requested_node: N,
ensure_node_data_initialized(&requested_node);
ensure_element_styled(requested_node.as_element().unwrap(), style_context);

let layout_node = requested_node.to_threadsafe();
let layout_node = match *pseudo {
Some(PseudoElement::Before) => layout_node.get_before_pseudo(),
Some(PseudoElement::After) => layout_node.get_after_pseudo(),
let layout_el = requested_node.to_threadsafe().as_element().unwrap();

This comment has been minimized.

@emilio

emilio Oct 28, 2016

Member

Probably worth making this function take an Element directly. Can be a followup if it's too much pain.

This comment has been minimized.

@bholley

bholley Oct 28, 2016

Author Contributor

Turns out to be kinda hard to do because LayoutElement doesn't exist until #13956, and the opaque representations are all Node-y. We can do it later.

let layout_el = match *pseudo {
Some(PseudoElement::Before) => layout_el.get_before_pseudo(),
Some(PseudoElement::After) => layout_el.get_after_pseudo(),
Some(PseudoElement::DetailsSummary) |
Some(PseudoElement::DetailsContent) |
Some(PseudoElement::Selection) => None,
_ => Some(layout_node)
_ => Some(layout_el)
};

let layout_node = match layout_node {
let layout_el = match layout_el {
None => {
// The pseudo doesn't exist, return nothing. Chrome seems to query
// the element itself in this case, Firefox uses the resolved value.
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=29006
return None;
}
Some(layout_node) => layout_node
Some(layout_el) => layout_el
};

let style = &*layout_node.resolved_style();
let style = &*layout_el.resolved_style();

let positioned = match style.get_box().position {
position::computed_value::T::relative |
@@ -678,11 +678,11 @@ pub fn process_resolved_style_request<'a, N, C>(requested_node: N,
let applies = true;

fn used_value_for_position_property<N: LayoutNode>(
layout_node: N::ConcreteThreadSafeLayoutNode,
layout_el: <N::ConcreteThreadSafeLayoutNode as ThreadSafeLayoutNode>::ConcreteThreadSafeLayoutElement,
layout_root: &mut Flow,
requested_node: N,
property: &Atom) -> Option<String> {
let maybe_data = layout_node.borrow_layout_data();
let maybe_data = layout_el.borrow_layout_data();
let position = maybe_data.map_or(Point2D::zero(), |data| {
match (*data).flow_construction_result {
ConstructionResult::Flow(ref flow_ref, _) =>
@@ -744,12 +744,12 @@ pub fn process_resolved_style_request<'a, N, C>(requested_node: N,
atom!("left")
if applies && positioned && style.get_box().display !=
display::computed_value::T::none => {
used_value_for_position_property(layout_node, layout_root, requested_node, property)
used_value_for_position_property(layout_el, layout_root, requested_node, property)
}
atom!("width") | atom!("height")
if applies && style.get_box().display !=
display::computed_value::T::none => {
used_value_for_position_property(layout_node, layout_root, requested_node, property)
used_value_for_position_property(layout_el, layout_root, requested_node, property)
}
// FIXME: implement used value computation for line-height
ref property => {
@@ -781,7 +781,7 @@ pub fn process_offset_parent_query<N: LayoutNode>(requested_node: N, layout_root

pub fn process_node_overflow_request<N: LayoutNode>(requested_node: N) -> NodeOverflowResponse {
let layout_node = requested_node.to_threadsafe();
let style = &*layout_node.resolved_style();
let style = &*layout_node.as_element().unwrap().resolved_style();
let style_box = style.get_box();

NodeOverflowResponse(Some((Point2D::new(style_box.overflow_x, style_box.overflow_y.0))))
@@ -790,7 +790,7 @@ pub fn process_node_overflow_request<N: LayoutNode>(requested_node: N) -> NodeOv
pub fn process_margin_style_query<N: LayoutNode>(requested_node: N)
-> MarginStyleResponse {
let layout_node = requested_node.to_threadsafe();
let style = &*layout_node.resolved_style();
let style = &*layout_node.as_element().unwrap().resolved_style();
let margin = style.get_margin();

MarginStyleResponse {
@@ -23,7 +23,7 @@ use style::traversal::{recalc_style_at, remove_from_bloom_filter};
use style::traversal::RestyleResult;
use style::traversal::take_thread_local_bloom_filter;
use util::opts;
use wrapper::{LayoutNodeLayoutData, ThreadSafeLayoutNodeHelpers};
use wrapper::{LayoutNodeHelpers, LayoutNodeLayoutData};

pub struct RecalcStyleAndConstructFlows<'lc> {
context: LayoutContext<'lc>,
@@ -33,7 +33,8 @@
use core::nonzero::NonZero;
use data::{LayoutDataFlags, PersistentLayoutData};
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialPersistentLayoutData};
use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode};
use script_layout_interface::wrapper_traits::{GetLayoutData, LayoutNode};
use script_layout_interface::wrapper_traits::{ThreadSafeLayoutElement, ThreadSafeLayoutNode};
use style::atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use style::computed_values::content::{self, ContentItem};

@@ -44,11 +45,10 @@ pub trait LayoutNodeLayoutData {
/// than only the style::data::NodeData.
fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>>;
fn mutate_layout_data(&self) -> Option<AtomicRefMut<PersistentLayoutData>>;
fn initialize_data(self);
fn flow_debug_id(self) -> usize;
}

impl<T: LayoutNode> LayoutNodeLayoutData for T {
impl<T: GetLayoutData> LayoutNodeLayoutData for T {
fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>> {
unsafe {
self.get_style_and_layout_data().map(|opaque| {
@@ -67,6 +67,16 @@ impl<T: LayoutNode> LayoutNodeLayoutData for T {
}
}

fn flow_debug_id(self) -> usize {
self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
}
}

pub trait LayoutNodeHelpers {
fn initialize_data(self);
}

impl<T: LayoutNode> LayoutNodeHelpers for T {
fn initialize_data(self) {
if self.borrow_layout_data().is_none() {
let ptr: NonOpaqueStyleAndLayoutData =
@@ -77,27 +87,9 @@ impl<T: LayoutNode> LayoutNodeLayoutData for T {
self.init_style_and_layout_data(opaque);
}
}

fn flow_debug_id(self) -> usize {
self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
}
}

pub trait ThreadSafeLayoutNodeHelpers {
fn flow_debug_id(self) -> usize;

/// Borrows the layout data immutably. Fails on a conflicting borrow.
///
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
#[inline(always)]
fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>>;

/// Borrows the layout data mutably. Fails on a conflicting borrow.
///
/// TODO(pcwalton): Make this private. It will let us avoid borrow flag checks in some cases.
#[inline(always)]
fn mutate_layout_data(&self) -> Option<AtomicRefMut<PersistentLayoutData>>;

/// Returns the layout data flags for this node.
fn flags(self) -> LayoutDataFlags;

@@ -115,28 +107,6 @@ pub trait ThreadSafeLayoutNodeHelpers {
}

impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T {
fn flow_debug_id(self) -> usize {
self.borrow_layout_data().map_or(0, |d| d.flow_construction_result.debug_id())
}

fn borrow_layout_data(&self) -> Option<AtomicRef<PersistentLayoutData>> {
unsafe {
self.get_style_and_layout_data().map(|opaque| {
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
(*container).borrow()
})
}
}

fn mutate_layout_data(&self) -> Option<AtomicRefMut<PersistentLayoutData>> {
unsafe {
self.get_style_and_layout_data().map(|opaque| {
let container = *opaque.ptr as NonOpaqueStyleAndLayoutData;
(*container).borrow_mut()
})
}
}

fn flags(self) -> LayoutDataFlags {
self.borrow_layout_data().as_ref().unwrap().flags
}
@@ -151,7 +121,7 @@ impl<T: ThreadSafeLayoutNode> ThreadSafeLayoutNodeHelpers for T {

fn text_content(&self) -> TextContent {
if self.get_pseudo_element_type().is_replaced_content() {
let style = self.resolved_style();
let style = self.as_element().unwrap().resolved_style();

return match style.as_ref().get_counters().content {
content::T::Content(ref value) if !value.is_empty() => {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.