diff options
author | Alan Jeffrey <ajeffrey@mozilla.com> | 2017-09-14 15:53:12 -0500 |
---|---|---|
committer | Alan Jeffrey <ajeffrey@mozilla.com> | 2017-09-22 09:04:18 -0500 |
commit | fbfb9a80b4f23854c984c7039c8dc30a8eb583b1 (patch) | |
tree | 937b48c64482d7d188804844bd5b0dbd0f2ca7f0 /components/script/script_thread.rs | |
parent | 6a791cd7f26b42a6688099bea203c21fb3c9cc12 (diff) | |
download | servo-fbfb9a80b4f23854c984c7039c8dc30a8eb583b1.tar.gz servo-fbfb9a80b4f23854c984c7039c8dc30a8eb583b1.zip |
Remove sources of panic when laying out an iframe without a nested browsing context.
Diffstat (limited to 'components/script/script_thread.rs')
-rw-r--r-- | components/script/script_thread.rs | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 2fa0071ed65..b9bcf5be7c8 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -1750,10 +1750,35 @@ impl ScriptThread { load.pipeline_id == id }); + let document = self.documents.borrow_mut().remove(id); + + // We should never have a pipeline that's still an incomplete load, + // but also has a Document. + debug_assert!(idx.is_none() || document.is_none()); + + // Remove any incomplete load. let chan = if let Some(idx) = idx { let load = self.incomplete_loads.borrow_mut().remove(idx); load.layout_chan.clone() - } else if let Some(document) = self.documents.borrow_mut().remove(id) { + } else if let Some(ref document) = document { + document.window().layout_chan().clone() + } else { + return warn!("Exiting nonexistant pipeline {}.", id); + }; + + // We shut down layout before removing the document, + // since layout might still be in the middle of laying it out. + debug!("preparing to shut down layout for page {}", id); + let (response_chan, response_port) = channel(); + chan.send(message::Msg::PrepareToExit(response_chan)).ok(); + let _ = response_port.recv(); + + debug!("shutting down layout for page {}", id); + chan.send(message::Msg::ExitNow).ok(); + self.script_sender.send((id, ScriptMsg::PipelineExited)).ok(); + + // Now that layout is shut down, it's OK to remove the document. + if let Some(document) = document { // We don't want to dispatch `mouseout` event pointing to non-existing element if let Some(target) = self.topmost_mouse_over_target.get() { if target.upcast::<Node>().owner_doc() == document { @@ -1761,22 +1786,14 @@ impl ScriptThread { } } + // We discard the browsing context after requesting layout shut down, + // to avoid running layout on detached iframes. let window = document.window(); if discard_bc == DiscardBrowsingContext::Yes { window.window_proxy().discard_browsing_context(); } window.clear_js_runtime(); - window.layout_chan().clone() - } else { - return warn!("Exiting nonexistant pipeline {}.", id); - }; - - let (response_chan, response_port) = channel(); - chan.send(message::Msg::PrepareToExit(response_chan)).ok(); - debug!("shutting down layout for page {}", id); - let _ = response_port.recv(); - chan.send(message::Msg::ExitNow).ok(); - self.script_sender.send((id, ScriptMsg::PipelineExited)).ok(); + } debug!("Exited pipeline {}.", id); } |