diff options
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); } |