Make FlowRef a newtype

This creates a sharp distinction between `Arc<Flow>`s, which may be
owned by anyone, and `FlowRef`s, which may only be owned by the
traversal code. By checking the reference count, we ensure that a `Flow`
cannot be pointed to by `Arc`s and `FlowRef`s simultaneously.

This is not a complete fix for #6503, though it is a necessary start
(enforcing the no-aliasing rule of `FlowRef::deref_mut` will require far
more work).

Fixes #14014
This commit is contained in:
Michael Howell 2016-11-03 12:53:27 -07:00
parent 5b4cc9568d
commit 5f320bd2ca
10 changed files with 145 additions and 101 deletions

View file

@ -12,7 +12,7 @@ use context::{LayoutContext, SharedLayoutContext};
use euclid::{Point2D, Rect, Size2D};
use floats::ClearType;
use flow::{self, ImmutableFlowUtils};
use flow_ref::{self, FlowRef};
use flow_ref::FlowRef;
use gfx;
use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
use gfx::text::glyph::ByteIndex;
@ -1985,7 +1985,7 @@ impl Fragment {
match self.specific {
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
let block_flow = flow_ref::deref_mut(&mut info.flow_ref).as_mut_block();
let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_mut_block();
block_flow.base.position.size.inline =
block_flow.base.intrinsic_inline_sizes.preferred_inline_size;
@ -1993,7 +1993,7 @@ impl Fragment {
self.border_box.size.inline = Au(0);
}
SpecificFragmentInfo::InlineBlock(ref mut info) => {
let block_flow = flow_ref::deref_mut(&mut info.flow_ref).as_mut_block();
let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_mut_block();
self.border_box.size.inline =
max(block_flow.base.intrinsic_inline_sizes.minimum_inline_size,
block_flow.base.intrinsic_inline_sizes.preferred_inline_size);
@ -2001,7 +2001,7 @@ impl Fragment {
block_flow.base.block_container_writing_mode = self.style.writing_mode;
}
SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
let block_flow = flow_ref::deref_mut(&mut info.flow_ref).as_mut_block();
let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_mut_block();
self.border_box.size.inline =
max(block_flow.base.intrinsic_inline_sizes.minimum_inline_size,
block_flow.base.intrinsic_inline_sizes.preferred_inline_size);
@ -2133,18 +2133,18 @@ impl Fragment {
}
SpecificFragmentInfo::InlineBlock(ref mut info) => {
// Not the primary fragment, so we do not take the noncontent size into account.
let block_flow = flow_ref::deref_mut(&mut info.flow_ref).as_block();
let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_block();
self.border_box.size.block = block_flow.base.position.size.block +
block_flow.fragment.margin.block_start_end()
}
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
// Not the primary fragment, so we do not take the noncontent size into account.
let block_flow = flow_ref::deref_mut(&mut info.flow_ref).as_block();
let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_block();
self.border_box.size.block = block_flow.base.position.size.block;
}
SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
// Not the primary fragment, so we do not take the noncontent size into account.
let block_flow = flow_ref::deref_mut(&mut info.flow_ref).as_block();
let block_flow = FlowRef::deref_mut(&mut info.flow_ref).as_block();
self.border_box.size.block = block_flow.base.position.size.block +
block_flow.fragment.margin.block_start_end()
}
@ -2481,7 +2481,7 @@ impl Fragment {
/// block size assignment.
pub fn update_late_computed_replaced_inline_size_if_necessary(&mut self) {
if let SpecificFragmentInfo::InlineBlock(ref mut inline_block_info) = self.specific {
let block_flow = flow_ref::deref_mut(&mut inline_block_info.flow_ref).as_block();
let block_flow = FlowRef::deref_mut(&mut inline_block_info.flow_ref).as_block();
let margin = block_flow.fragment.style.logical_margin();
self.border_box.size.inline = block_flow.fragment.border_box.size.inline +
MaybeAuto::from_style(margin.inline_start, Au(0)).specified_or_zero() +
@ -2492,7 +2492,7 @@ impl Fragment {
pub fn update_late_computed_inline_position_if_necessary(&mut self) {
if let SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) = self.specific {
let position = self.border_box.start.i;
flow_ref::deref_mut(&mut info.flow_ref)
FlowRef::deref_mut(&mut info.flow_ref)
.update_late_computed_inline_position_if_necessary(position)
}
}
@ -2500,7 +2500,7 @@ impl Fragment {
pub fn update_late_computed_block_position_if_necessary(&mut self) {
if let SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) = self.specific {
let position = self.border_box.start.b;
flow_ref::deref_mut(&mut info.flow_ref)
FlowRef::deref_mut(&mut info.flow_ref)
.update_late_computed_block_position_if_necessary(position)
}
}