From 36fbbea2b558c6646d58d217c9103a320d451fc7 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 3 Jul 2020 03:33:59 +0200 Subject: [PATCH] Return Option for Window's layout channel --- components/script/dom/document.rs | 32 +++++++++-------- components/script/dom/window.rs | 35 +++++++++++++------ components/script/script_thread.rs | 19 ++++++---- tests/wpt/mozilla/meta/MANIFEST.json | 7 ++++ .../tests/mozilla/detached_layout.html | 23 ++++++++++++ 5 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 tests/wpt/mozilla/tests/mozilla/detached_layout.html diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 09b802b20e5..0c0b7b01425 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -799,10 +799,10 @@ impl Document { self.quirks_mode.set(mode); if mode == QuirksMode::Quirks { - self.window - .layout_chan() - .send(Msg::SetQuirksMode(mode)) - .unwrap(); + match self.window.layout_chan() { + Some(chan) => chan.send(Msg::SetQuirksMode(mode)).unwrap(), + None => warn!("Layout channel unavailable"), + } } } @@ -3703,13 +3703,15 @@ impl Document { }) .cloned(); - self.window - .layout_chan() - .send(Msg::AddStylesheet( - sheet.clone(), - insertion_point.as_ref().map(|s| s.sheet.clone()), - )) - .unwrap(); + match self.window.layout_chan() { + Some(chan) => chan + .send(Msg::AddStylesheet( + sheet.clone(), + insertion_point.as_ref().map(|s| s.sheet.clone()), + )) + .unwrap(), + None => return warn!("Layout channel unavailable"), + } DocumentOrShadowRoot::add_stylesheet( owner, @@ -3723,10 +3725,10 @@ impl Document { /// Remove a stylesheet owned by `owner` from the list of document sheets. #[allow(unrooted_must_root)] // Owner needs to be rooted already necessarily. pub fn remove_stylesheet(&self, owner: &Element, s: &Arc) { - self.window - .layout_chan() - .send(Msg::RemoveStylesheet(s.clone())) - .unwrap(); + match self.window.layout_chan() { + Some(chan) => chan.send(Msg::RemoveStylesheet(s.clone())).unwrap(), + None => return warn!("Layout channel unavailable"), + } DocumentOrShadowRoot::remove_stylesheet( owner, diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index b555300e219..6f95104a323 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -224,6 +224,9 @@ pub struct Window { js_runtime: DomRefCell>>, /// A handle for communicating messages to the layout thread. + /// + /// This channel shouldn't be accessed directly, but through `Window::layout_chan()`, + /// which returns `None` if there's no layout thread anymore. #[ignore_malloc_size_of = "channels are hard"] layout_chan: Sender, @@ -1553,12 +1556,15 @@ impl Window { // TODO Step 1 // TODO(mrobinson, #18709): Add smooth scrolling support to WebRender so that we can // properly process ScrollBehavior here. - self.layout_chan - .send(Msg::UpdateScrollStateFromScript(ScrollState { - scroll_id, - scroll_offset: Vector2D::new(-x, -y), - })) - .unwrap(); + match self.layout_chan() { + Some(chan) => chan + .send(Msg::UpdateScrollStateFromScript(ScrollState { + scroll_id, + scroll_offset: Vector2D::new(-x, -y), + })) + .unwrap(), + None => warn!("Layout channel unavailable"), + } } pub fn update_viewport_for_scroll(&self, x: f32, y: f32) { @@ -1696,9 +1702,12 @@ impl Window { animations: document.animations().sets.clone(), }; - self.layout_chan - .send(Msg::Reflow(reflow)) - .expect("Layout thread disconnected."); + match self.layout_chan() { + Some(layout_chan) => layout_chan + .send(Msg::Reflow(reflow)) + .expect("Layout thread disconnected"), + None => return false, + }; debug!("script: layout forked"); @@ -2102,8 +2111,12 @@ impl Window { self.Document().url() } - pub fn layout_chan(&self) -> &Sender { - &self.layout_chan + pub fn layout_chan(&self) -> Option<&Sender> { + if self.is_alive() { + Some(&self.layout_chan) + } else { + None + } } pub fn windowproxy_handler(&self) -> WindowProxyHandler { diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 0ef48e78b17..067fce6b08e 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -1172,9 +1172,13 @@ impl ScriptThread { ); }, }; - let _ = window - .layout_chan() - .send(Msg::RegisterPaint(name, properties, painter)); + + match window.layout_chan() { + Some(chan) => chan + .send(Msg::RegisterPaint(name, properties, painter)) + .unwrap(), + None => warn!("Layout channel unavailable"), + } } pub fn push_new_element_queue() { @@ -2467,12 +2471,12 @@ impl ScriptThread { }); // Pick a layout thread, any layout thread - let current_layout_chan = self + let current_layout_chan: Option> = self .documents .borrow() .iter() .next() - .map(|(_, document)| document.window().layout_chan().clone()) + .and_then(|(_, document)| document.window().layout_chan().cloned()) .or_else(|| { self.incomplete_loads .borrow() @@ -2879,7 +2883,10 @@ impl ScriptThread { let load = self.incomplete_loads.borrow_mut().remove(idx); load.layout_chan.clone() } else if let Some(ref document) = document { - document.window().layout_chan().clone() + match document.window().layout_chan() { + Some(chan) => chan.clone(), + None => return warn!("Layout channel unavailable"), + } } else { return warn!("Exiting nonexistant pipeline {}.", id); }; diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 9e38fdaca6f..1c43211a3e1 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -13361,6 +13361,13 @@ {} ] ], + "detached_layout.html": [ + "b9fe090cc29c147f493732327e36b06702c4f846", + [ + null, + {} + ] + ], "deterministic-raf.html": [ "441664829a14379ebc92306f42ab0bad6581257e", [ diff --git a/tests/wpt/mozilla/tests/mozilla/detached_layout.html b/tests/wpt/mozilla/tests/mozilla/detached_layout.html new file mode 100644 index 00000000000..b9fe090cc29 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/detached_layout.html @@ -0,0 +1,23 @@ + + +Detached layout doesn't panic + + + +