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

Fix various crashes, leaks, and cycles #468

Closed
wants to merge 6 commits into from

Add teardown phase to the start of each layout operation that manuall…

…y breaks cycles between flows, boxes, fonts, shapers, and textruns on stale layout data.
  • Loading branch information
jdm committed May 22, 2013
commit ec4f16fa681c0d1412b43809eef5381487637520
@@ -177,6 +177,10 @@ pub impl FontGroup {
}
}

fn teardown(&mut self) {
self.fonts = ~[];
}

fn create_textrun(&self, text: ~str) -> TextRun {
assert!(self.fonts.len() > 0);

@@ -283,6 +287,11 @@ pub impl Font {
return result;
}

fn teardown(&mut self) {
self.shaper = None;
self.azure_font = None;
}

// TODO: this should return a borrowed pointer, but I can't figure
// out why borrowck doesn't like my implementation.

@@ -51,6 +51,10 @@ pub impl<'self> TextRun {
return run;
}

fn teardown(&self) {
self.font.teardown();
}

fn compute_potential_breaks(text: &str, glyphs: &mut GlyphStore) {
// TODO(Issue #230): do a better job. See Gecko's LineBreaker.

@@ -18,6 +18,14 @@ impl LayoutAuxMethods for AbstractNode {
/// box in the COW model) and populates it with an empty style object.
fn initialize_layout_data(self) -> Option<@mut LayoutData> {
if self.has_layout_data() {
{
let layout_data = &mut self.layout_data().flow;
match *layout_data {
Some(ref flow) => flow.teardown(),
None => ()
}
}
self.layout_data().flow = None;
None
} else {
let data = @mut LayoutData::new();
@@ -45,6 +45,14 @@ impl BlockFlowData {
is_root: true
}
}

pub fn teardown(&mut self) {
self.common.teardown();
for self.box.each |box| {
box.teardown();
}
self.box = None;
}
}

pub trait BlockLayout {
@@ -59,6 +59,15 @@ pub enum RenderBox {
UnscannedTextRenderBoxClass(@mut UnscannedTextRenderBox),
}

impl RenderBox {
pub fn teardown(&self) {
match *self {
TextRenderBoxClass(box) => box.teardown(),
_ => ()
}
}
}

/// A box that represents a (replaced content) image and its accompanying borders, shadows, etc.
pub struct ImageRenderBox {
base: RenderBoxBase,
@@ -88,6 +97,12 @@ pub struct TextRenderBox {
text_data: TextBoxData,
}

impl TextRenderBox {
fn teardown(&self) {
self.text_data.teardown();
}
}

/// The data for an unscanned text box.
pub struct UnscannedTextRenderBox {
base: RenderBoxBase,
@@ -67,6 +67,43 @@ impl Clone for FlowContext {
}
}

impl FlowContext {
pub fn teardown(&self) {
match *self {
AbsoluteFlow(data) |
FloatFlow(data) |
InlineBlockFlow(data) |
TableFlow(data) => data.teardown(),
BlockFlow(data) => data.teardown(),
InlineFlow(data) => data.teardown()
}
}
}

impl FlowData {
pub fn teardown(&mut self) {
// Under the assumption that all flows exist in a tree,
// we must restrict ourselves to finalizing flows that
// are descendents and subsequent siblings to ourselves,
// or we risk dynamic borrow failures.
self.parent = None;

for self.first_child.each |flow| {
flow.teardown();
}
self.first_child = None;

self.last_child = None;

for self.next_sibling.each |flow| {
flow.teardown();
}
self.next_sibling = None;

self.prev_sibling = None;
}
}

impl TreeNodeRef<FlowData> for FlowContext {
fn with_base<R>(&self, callback: &fn(&FlowData) -> R) -> R {
match *self {
@@ -638,6 +638,14 @@ impl InlineFlowData {
elems: ElementMapping::new(),
}
}

pub fn teardown(&mut self) {
self.common.teardown();
for self.boxes.each |box| {
box.teardown();
}
self.boxes = ~[];
}
}

pub trait InlineLayout {
@@ -21,6 +21,10 @@ impl TextBoxData {
range: range,
}
}

pub fn teardown(&self) {
self.run.teardown();
}
}

pub fn adapt_textbox_with_range(mut base: RenderBoxBase, run: @TextRun, range: Range)
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.