diff options
Diffstat (limited to 'components/script/dom/window.rs')
-rw-r--r-- | components/script/dom/window.rs | 555 |
1 files changed, 355 insertions, 200 deletions
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 4c5e955cded..ff905ab55b5 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -139,7 +139,7 @@ use webvr_traits::WebVRMsg; #[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf, PartialEq)] enum WindowState { Alive, - Zombie, // Pipeline is closed, but the window hasn't been GCed yet. + Zombie, // Pipeline is closed, but the window hasn't been GCed yet. } /// Extra information concerning the reason for reflowing. @@ -332,7 +332,9 @@ impl Window { fn ignore_all_events(&self) { let mut ignore_flags = self.ignore_further_async_events.borrow_mut(); for task_source_name in TaskSourceName::all() { - let flag = ignore_flags.entry(task_source_name).or_insert(Default::default()); + let flag = ignore_flags + .entry(task_source_name) + .or_insert(Default::default()); flag.store(true, Ordering::Relaxed); } } @@ -407,12 +409,13 @@ impl Window { /// Returns the window proxy if it has not been discarded. /// <https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded> pub fn undiscarded_window_proxy(&self) -> Option<DomRoot<WindowProxy>> { - self.window_proxy.get() - .and_then(|window_proxy| if window_proxy.is_browsing_context_discarded() { + self.window_proxy.get().and_then(|window_proxy| { + if window_proxy.is_browsing_context_discarded() { None } else { Some(window_proxy) - }) + } + }) } pub fn bluetooth_thread(&self) -> IpcSender<BluetoothRequest> { @@ -420,7 +423,7 @@ impl Window { } pub fn bluetooth_extra_permission_data(&self) -> &BluetoothExtraPermissionData { - &self.bluetooth_extra_permission_data + &self.bluetooth_extra_permission_data } pub fn css_error_reporter(&self) -> Option<&ParseErrorReporter> { @@ -451,7 +454,9 @@ impl Window { Worklet::new(self, WorkletGlobalScopeType::Paint) } - pub fn permission_state_invocation_results(&self) -> &DomRefCell<HashMap<String, PermissionState>> { + pub fn permission_state_invocation_results( + &self, + ) -> &DomRefCell<HashMap<String, PermissionState>> { &self.permission_state_invocation_results } @@ -469,10 +474,12 @@ impl Window { node.dirty(NodeDamage::OtherNodeDamage); } match response.response { - ImageResponse::MetadataLoaded(_) => {} + ImageResponse::MetadataLoaded(_) => {}, ImageResponse::Loaded(_, _) | ImageResponse::PlaceholderLoaded(_, _) | - ImageResponse::None => { nodes.remove(); } + ImageResponse::None => { + nodes.remove(); + }, } self.add_pending_reflow(); } @@ -504,7 +511,8 @@ pub fn base64_atob(input: DOMString) -> Fallible<DOMString> { fn is_html_space(c: char) -> bool { HTML_SPACE_CHARACTERS.iter().any(|&m| m == c) } - let without_spaces = input.chars() + let without_spaces = input + .chars() .filter(|&c| !is_html_space(c)) .collect::<String>(); let mut input = &*without_spaces; @@ -523,7 +531,7 @@ pub fn base64_atob(input: DOMString) -> Fallible<DOMString> { // "If the length of input divides by 4 leaving a remainder of 1, // throw an InvalidCharacterError exception and abort these steps." if input.len() % 4 == 1 { - return Err(Error::InvalidCharacter) + return Err(Error::InvalidCharacter); } // "If input contains a character that is not in the following list of @@ -533,13 +541,18 @@ pub fn base64_atob(input: DOMString) -> Fallible<DOMString> { // U+002B PLUS SIGN (+) // U+002F SOLIDUS (/) // Alphanumeric ASCII characters" - if input.chars().any(|c| c != '+' && c != '/' && !c.is_alphanumeric()) { - return Err(Error::InvalidCharacter) + if input + .chars() + .any(|c| c != '+' && c != '/' && !c.is_alphanumeric()) + { + return Err(Error::InvalidCharacter); } match base64::decode(&input) { - Ok(data) => Ok(DOMString::from(data.iter().map(|&b| b as char).collect::<String>())), - Err(..) => Err(Error::InvalidCharacter) + Ok(data) => Ok(DOMString::from( + data.iter().map(|&b| b as char).collect::<String>(), + )), + Err(..) => Err(Error::InvalidCharacter), } } @@ -563,7 +576,8 @@ impl WindowMethods for Window { stdout.flush().unwrap(); stderr.flush().unwrap(); } - let (sender, receiver) = ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap(); + let (sender, receiver) = + ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap(); let msg = EmbedderMsg::Alert(s.to_string(), sender); self.send_to_embedder(msg); receiver.recv().unwrap(); @@ -577,11 +591,12 @@ impl WindowMethods for Window { } // https://html.spec.whatwg.org/multipage/#dom-open - fn Open(&self, - url: DOMString, - target: DOMString, - features: DOMString) - -> Option<DomRoot<WindowProxy>> { + fn Open( + &self, + url: DOMString, + target: DOMString, + features: DOMString, + ) -> Option<DomRoot<WindowProxy>> { self.window_proxy().open(url, target, features) } @@ -600,16 +615,19 @@ impl WindowMethods for Window { } // Step 2. let obj = self.reflector().get_jsobject(); - assert!(JS_DefineProperty(cx, - obj, - "opener\0".as_ptr() as *const libc::c_char, - value, - JSPROP_ENUMERATE as u32)); + assert!(JS_DefineProperty( + cx, + obj, + "opener\0".as_ptr() as *const libc::c_char, + value, + JSPROP_ENUMERATE as u32 + )); } // https://html.spec.whatwg.org/multipage/#dom-window-closed fn Closed(&self) -> bool { - self.window_proxy.get() + self.window_proxy + .get() .map(|ref proxy| proxy.is_browsing_context_discarded()) .unwrap_or(true) } @@ -641,7 +659,9 @@ impl WindowMethods for Window { // https://html.spec.whatwg.org/multipage/#dom-document-2 fn Document(&self) -> DomRoot<Document> { - self.document.get().expect("Document accessed before initialization.") + self.document + .get() + .expect("Document accessed before initialization.") } // https://html.spec.whatwg.org/multipage/#dom-history @@ -651,7 +671,8 @@ impl WindowMethods for Window { // https://html.spec.whatwg.org/multipage/#dom-window-customelements fn CustomElements(&self) -> DomRoot<CustomElementRegistry> { - self.custom_element_registry.or_init(|| CustomElementRegistry::new(self)) + self.custom_element_registry + .or_init(|| CustomElementRegistry::new(self)) } // https://html.spec.whatwg.org/multipage/#dom-location @@ -661,12 +682,14 @@ impl WindowMethods for Window { // https://html.spec.whatwg.org/multipage/#dom-sessionstorage fn SessionStorage(&self) -> DomRoot<Storage> { - self.session_storage.or_init(|| Storage::new(self, StorageType::Session)) + self.session_storage + .or_init(|| Storage::new(self, StorageType::Session)) } // https://html.spec.whatwg.org/multipage/#dom-localstorage fn LocalStorage(&self) -> DomRoot<Storage> { - self.local_storage.or_init(|| Storage::new(self, StorageType::Local)) + self.local_storage + .or_init(|| Storage::new(self, StorageType::Local)) } // https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#dfn-GlobalCrypto @@ -684,8 +707,14 @@ impl WindowMethods for Window { // Step 6. let container_doc = document_from_node(container); - let current_doc = GlobalScope::current().expect("No current global object").as_window().Document(); - if !current_doc.origin().same_origin_domain(container_doc.origin()) { + let current_doc = GlobalScope::current() + .expect("No current global object") + .as_window() + .Document(); + if !current_doc + .origin() + .same_origin_domain(container_doc.origin()) + { return None; } // Step 7. @@ -699,51 +728,76 @@ impl WindowMethods for Window { #[allow(unsafe_code)] // https://html.spec.whatwg.org/multipage/#dom-windowtimers-settimeout - unsafe fn SetTimeout(&self, _cx: *mut JSContext, callback: Rc<Function>, timeout: i32, - args: Vec<HandleValue>) -> i32 { + unsafe fn SetTimeout( + &self, + _cx: *mut JSContext, + callback: Rc<Function>, + timeout: i32, + args: Vec<HandleValue>, + ) -> i32 { self.upcast::<GlobalScope>().set_timeout_or_interval( TimerCallback::FunctionTimerCallback(callback), args, timeout, - IsInterval::NonInterval) + IsInterval::NonInterval, + ) } #[allow(unsafe_code)] // https://html.spec.whatwg.org/multipage/#dom-windowtimers-settimeout - unsafe fn SetTimeout_(&self, _cx: *mut JSContext, callback: DOMString, - timeout: i32, args: Vec<HandleValue>) -> i32 { + unsafe fn SetTimeout_( + &self, + _cx: *mut JSContext, + callback: DOMString, + timeout: i32, + args: Vec<HandleValue>, + ) -> i32 { self.upcast::<GlobalScope>().set_timeout_or_interval( TimerCallback::StringTimerCallback(callback), args, timeout, - IsInterval::NonInterval) + IsInterval::NonInterval, + ) } // https://html.spec.whatwg.org/multipage/#dom-windowtimers-cleartimeout fn ClearTimeout(&self, handle: i32) { - self.upcast::<GlobalScope>().clear_timeout_or_interval(handle); + self.upcast::<GlobalScope>() + .clear_timeout_or_interval(handle); } #[allow(unsafe_code)] // https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval - unsafe fn SetInterval(&self, _cx: *mut JSContext, callback: Rc<Function>, - timeout: i32, args: Vec<HandleValue>) -> i32 { + unsafe fn SetInterval( + &self, + _cx: *mut JSContext, + callback: Rc<Function>, + timeout: i32, + args: Vec<HandleValue>, + ) -> i32 { self.upcast::<GlobalScope>().set_timeout_or_interval( TimerCallback::FunctionTimerCallback(callback), args, timeout, - IsInterval::Interval) + IsInterval::Interval, + ) } #[allow(unsafe_code)] // https://html.spec.whatwg.org/multipage/#dom-windowtimers-setinterval - unsafe fn SetInterval_(&self, _cx: *mut JSContext, callback: DOMString, - timeout: i32, args: Vec<HandleValue>) -> i32 { + unsafe fn SetInterval_( + &self, + _cx: *mut JSContext, + callback: DOMString, + timeout: i32, + args: Vec<HandleValue>, + ) -> i32 { self.upcast::<GlobalScope>().set_timeout_or_interval( TimerCallback::StringTimerCallback(callback), args, timeout, - IsInterval::Interval) + IsInterval::Interval, + ) } // https://html.spec.whatwg.org/multipage/#dom-windowtimers-clearinterval @@ -799,8 +853,11 @@ impl WindowMethods for Window { fn Performance(&self) -> DomRoot<Performance> { self.performance.or_init(|| { let global_scope = self.upcast::<GlobalScope>(); - Performance::new(global_scope, self.navigation_start.get(), - self.navigation_start_precise.get()) + Performance::new( + global_scope, + self.navigation_start.get(), + self.navigation_start_precise.get(), + ) }) } @@ -839,11 +896,12 @@ impl WindowMethods for Window { #[allow(unsafe_code)] // https://html.spec.whatwg.org/multipage/#dom-window-postmessage - unsafe fn PostMessage(&self, - cx: *mut JSContext, - message: HandleValue, - origin: DOMString) - -> ErrorResult { + unsafe fn PostMessage( + &self, + cx: *mut JSContext, + message: HandleValue, + origin: DOMString, + ) -> ErrorResult { // Step 3-5. let origin = match &origin[..] { "*" => None, @@ -855,7 +913,7 @@ impl WindowMethods for Window { url => match ServoUrl::parse(&url) { Ok(url) => Some(url.origin().clone()), Err(_) => return Err(Error::Syntax), - } + }, }; // Step 1-2, 6-8. @@ -892,7 +950,9 @@ impl WindowMethods for Window { #[allow(unsafe_code)] fn Trap(&self) { #[cfg(feature = "unstable")] - unsafe { ::std::intrinsics::breakpoint() } + unsafe { + ::std::intrinsics::breakpoint() + } } #[allow(unsafe_code)] @@ -912,39 +972,50 @@ impl WindowMethods for Window { } // https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle - fn GetComputedStyle(&self, - element: &Element, - pseudo: Option<DOMString>) -> DomRoot<CSSStyleDeclaration> { + fn GetComputedStyle( + &self, + element: &Element, + pseudo: Option<DOMString>, + ) -> DomRoot<CSSStyleDeclaration> { // Steps 1-4. - let pseudo = match pseudo.map(|mut s| { s.make_ascii_lowercase(); s }) { - Some(ref pseudo) if pseudo == ":before" || pseudo == "::before" => - Some(PseudoElement::Before), - Some(ref pseudo) if pseudo == ":after" || pseudo == "::after" => - Some(PseudoElement::After), - _ => None + let pseudo = match pseudo.map(|mut s| { + s.make_ascii_lowercase(); + s + }) { + Some(ref pseudo) if pseudo == ":before" || pseudo == "::before" => { + Some(PseudoElement::Before) + }, + Some(ref pseudo) if pseudo == ":after" || pseudo == "::after" => { + Some(PseudoElement::After) + }, + _ => None, }; // Step 5. - CSSStyleDeclaration::new(self, - CSSStyleOwner::Element(Dom::from_ref(element)), - pseudo, - CSSModificationAccess::Readonly) + CSSStyleDeclaration::new( + self, + CSSStyleOwner::Element(Dom::from_ref(element)), + pseudo, + CSSModificationAccess::Readonly, + ) } // https://drafts.csswg.org/cssom-view/#dom-window-innerheight //TODO Include Scrollbar fn InnerHeight(&self) -> i32 { - self.window_size.get() - .and_then(|e| e.initial_viewport.height.to_i32()) - .unwrap_or(0) + self.window_size + .get() + .and_then(|e| e.initial_viewport.height.to_i32()) + .unwrap_or(0) } // https://drafts.csswg.org/cssom-view/#dom-window-innerwidth //TODO Include Scrollbar fn InnerWidth(&self) -> i32 { - self.window_size.get() - .and_then(|e| e.initial_viewport.width.to_i32()) - .unwrap_or(0) + self.window_size + .get() + .and_then(|e| e.initial_viewport.width.to_i32()) + .unwrap_or(0) } // https://drafts.csswg.org/cssom-view/#dom-window-scrollx @@ -973,7 +1044,6 @@ impl WindowMethods for Window { let left = options.left.unwrap_or(0.0f64); let top = options.top.unwrap_or(0.0f64); self.scroll(left, top, options.parent.behavior); - } // https://drafts.csswg.org/cssom-view/#dom-window-scroll @@ -992,7 +1062,7 @@ impl WindowMethods for Window { } // https://drafts.csswg.org/cssom-view/#dom-window-scrollby - fn ScrollBy(&self, options: &ScrollToOptions) { + fn ScrollBy(&self, options: &ScrollToOptions) { // Step 1 let x = options.left.unwrap_or(0.0f64); let y = options.top.unwrap_or(0.0f64); @@ -1001,11 +1071,11 @@ impl WindowMethods for Window { } // https://drafts.csswg.org/cssom-view/#dom-window-scrollby - fn ScrollBy_(&self, x: f64, y: f64) { + fn ScrollBy_(&self, x: f64, y: f64) { // Step 3 let left = x + self.ScrollX() as f64; // Step 4 - let top = y + self.ScrollY() as f64; + let top = y + self.ScrollY() as f64; // Step 5 self.scroll(left, top, ScrollBehavior::Auto); @@ -1024,7 +1094,10 @@ impl WindowMethods for Window { fn ResizeBy(&self, x: i32, y: i32) { let (size, _) = self.client_window(); // Step 1 - self.ResizeTo(x + size.width.to_i32().unwrap_or(1), y + size.height.to_i32().unwrap_or(1)) + self.ResizeTo( + x + size.width.to_i32().unwrap_or(1), + y + size.height.to_i32().unwrap_or(1), + ) } // https://drafts.csswg.org/cssom-view/#dom-window-moveto @@ -1097,8 +1170,7 @@ impl WindowMethods for Window { self.css_error_reporter(), None, ); - let media_query_list = - media_queries::MediaList::parse(&context, &mut parser); + let media_query_list = media_queries::MediaList::parse(&context, &mut parser); let document = self.Document(); let mql = MediaQueryList::new(&document, media_query_list); self.media_query_lists.track(&*mql); @@ -1107,7 +1179,11 @@ impl WindowMethods for Window { #[allow(unrooted_must_root)] // https://fetch.spec.whatwg.org/#fetch-method - fn Fetch(&self, input: RequestOrUSVString, init: RootedTraceableBox<RequestInit>) -> Rc<Promise> { + fn Fetch( + &self, + input: RequestOrUSVString, + init: RootedTraceableBox<RequestInit>, + ) -> Rc<Promise> { fetch::Fetch(&self.upcast(), input, init) } @@ -1160,7 +1236,9 @@ impl Window { pub fn cancel_all_tasks(&self) { let mut ignore_flags = self.ignore_further_async_events.borrow_mut(); for task_source_name in TaskSourceName::all() { - let flag = ignore_flags.entry(task_source_name).or_insert(Default::default()); + let flag = ignore_flags + .entry(task_source_name) + .or_insert(Default::default()); let cancelled = mem::replace(&mut *flag, Default::default()); cancelled.store(true, Ordering::Relaxed); } @@ -1171,7 +1249,9 @@ impl Window { /// `true` and replaces it with a brand new one for future tasks. pub fn cancel_all_tasks_from_source(&self, task_source_name: TaskSourceName) { let mut ignore_flags = self.ignore_further_async_events.borrow_mut(); - let flag = ignore_flags.entry(task_source_name).or_insert(Default::default()); + let flag = ignore_flags + .entry(task_source_name) + .or_insert(Default::default()); let cancelled = mem::replace(&mut *flag, Default::default()); cancelled.store(true, Ordering::Relaxed); } @@ -1234,12 +1314,12 @@ impl Window { let content_size = e.upcast::<Node>().bounding_content_box_or_zero(); let content_height = content_size.size.height.to_f64_px(); let content_width = content_size.size.width.to_f64_px(); - (xfinite.min(content_width - width).max(0.0f64), - yfinite.min(content_height - height).max(0.0f64)) + ( + xfinite.min(content_width - width).max(0.0f64), + yfinite.min(content_height - height).max(0.0f64), + ) }, - None => { - (xfinite.max(0.0f64), yfinite.max(0.0f64)) - } + None => (xfinite.max(0.0f64), yfinite.max(0.0f64)), }; // Step 10 @@ -1255,27 +1335,32 @@ impl Window { let x = x.to_f32().unwrap_or(0.0f32); let y = y.to_f32().unwrap_or(0.0f32); self.update_viewport_for_scroll(x, y); - self.perform_a_scroll(x, - y, - global_scope.pipeline_id().root_scroll_id(), - behavior, - None); + self.perform_a_scroll( + x, + y, + global_scope.pipeline_id().root_scroll_id(), + behavior, + None, + ); } /// <https://drafts.csswg.org/cssom-view/#perform-a-scroll> - pub fn perform_a_scroll(&self, - x: f32, - y: f32, - scroll_id: ExternalScrollId, - _behavior: ScrollBehavior, - _element: Option<&Element>) { + pub fn perform_a_scroll( + &self, + x: f32, + y: f32, + scroll_id: ExternalScrollId, + _behavior: ScrollBehavior, + _element: Option<&Element>, + ) { // 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(); + self.layout_chan + .send(Msg::UpdateScrollStateFromScript(ScrollState { + scroll_id, + scroll_offset: Vector2D::new(-x, -y), + })).unwrap(); } pub fn update_viewport_for_scroll(&self, x: f32, y: f32) { @@ -1285,7 +1370,9 @@ impl Window { } pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> { - self.window_size.get().map_or(TypedScale::new(1.0), |data| data.device_pixel_ratio) + self.window_size + .get() + .map_or(TypedScale::new(1.0), |data| data.device_pixel_ratio) } fn client_window(&self) -> (TypedSize2D<u32, CSSPixel>, TypedPoint2D<i32, CSSPixel>) { @@ -1293,15 +1380,22 @@ impl Window { let (send, recv) = ProfiledIpc::channel::<(DeviceUintSize, DeviceIntPoint)>(timer_profile_chan).unwrap(); self.send_to_constellation(ScriptMsg::GetClientWindow(send)); - let (size, point) = recv.recv().unwrap_or((TypedSize2D::zero(), TypedPoint2D::zero())); + let (size, point) = recv + .recv() + .unwrap_or((TypedSize2D::zero(), TypedPoint2D::zero())); let dpr = self.device_pixel_ratio(); - ((size.to_f32() / dpr).to_u32(), (point.to_f32() / dpr).to_i32()) + ( + (size.to_f32() / dpr).to_u32(), + (point.to_f32() / dpr).to_i32(), + ) } /// Advances the layout animation clock by `delta` milliseconds, and then /// forces a reflow if `tick` is true. pub fn advance_animation_clock(&self, delta: i32, tick: bool) { - self.layout_chan.send(Msg::AdvanceClockMs(delta, tick)).unwrap(); + self.layout_chan + .send(Msg::AdvanceClockMs(delta, tick)) + .unwrap(); } /// Reflows the page unconditionally if possible and not suppressed. This @@ -1319,8 +1413,7 @@ impl Window { // Check if we need to unsuppress reflow. Note that this needs to be // *before* any early bailouts, or reflow might never be unsuppresed! match reason { - ReflowReason::FirstLoad | - ReflowReason::RefreshTick => self.suppress_reflow.set(false), + ReflowReason::FirstLoad | ReflowReason::RefreshTick => self.suppress_reflow.set(false), _ => (), } @@ -1332,8 +1425,11 @@ impl Window { let for_display = reflow_goal == ReflowGoal::Full; if for_display && self.suppress_reflow.get() { - debug!("Suppressing reflow pipeline {} for reason {:?} before FirstLoad or RefreshTick", - self.upcast::<GlobalScope>().pipeline_id(), reason); + debug!( + "Suppressing reflow pipeline {} for reason {:?} before FirstLoad or RefreshTick", + self.upcast::<GlobalScope>().pipeline_id(), + reason + ); return false; } @@ -1350,7 +1446,11 @@ impl Window { // On debug mode, print the reflow event information. if opts::get().relayout_event { - debug_reflow_events(self.upcast::<GlobalScope>().pipeline_id(), &reflow_goal, &reason); + debug_reflow_events( + self.upcast::<GlobalScope>().pipeline_id(), + &reflow_goal, + &reason, + ); } let document = self.Document(); @@ -1411,15 +1511,23 @@ impl Window { let mut images = self.pending_layout_images.borrow_mut(); let nodes = images.entry(id).or_insert(vec![]); - if nodes.iter().find(|n| &***n as *const _ == &*node as *const _).is_none() { + if nodes + .iter() + .find(|n| &***n as *const _ == &*node as *const _) + .is_none() + { let (responder, responder_listener) = ProfiledIpc::channel(self.global().time_profiler_chan().clone()).unwrap(); let pipeline = self.upcast::<GlobalScope>().pipeline_id(); let image_cache_chan = self.image_cache_chan.clone(); - ROUTER.add_route(responder_listener.to_opaque(), Box::new(move |message| { - let _ = image_cache_chan.send((pipeline, message.to().unwrap())); - })); - self.image_cache.add_listener(id, ImageResponder::new(responder, id)); + ROUTER.add_route( + responder_listener.to_opaque(), + Box::new(move |message| { + let _ = image_cache_chan.send((pipeline, message.to().unwrap())); + }), + ); + self.image_cache + .add_listener(id, ImageResponder::new(responder, id)); nodes.push(Dom::from_ref(&*node)); } } @@ -1454,12 +1562,17 @@ impl Window { // If window_size is `None`, we don't reflow, so the document stays // dirty. Otherwise, we shouldn't need a reflow immediately after a // reflow, except if we're waiting for a deferred paint. - assert!(!self.Document().needs_reflow() || + assert!( + !self.Document().needs_reflow() || (!for_display && self.Document().needs_paint()) || self.window_size.get().is_none() || - self.suppress_reflow.get()); + self.suppress_reflow.get() + ); } else { - debug!("Document doesn't need reflow - skipping it (reason {:?})", reason); + debug!( + "Document doesn't need reflow - skipping it (reason {:?})", + reason + ); } // If writing a screenshot, check if the script has reached a state @@ -1472,7 +1585,9 @@ impl Window { // perspective at least). if (opts::get().output_file.is_some() || opts::get().exit_after_load || - opts::get().webdriver_port.is_some()) && for_display { + opts::get().webdriver_port.is_some()) && + for_display + { let document = self.Document(); // Checks if the html element has reftest-wait attribute present. @@ -1495,7 +1610,10 @@ impl Window { } pub fn layout_reflow(&self, query_msg: QueryMsg) -> bool { - self.reflow(ReflowGoal::LayoutQuery(query_msg, time::precise_time_ns()), ReflowReason::Query) + self.reflow( + ReflowGoal::LayoutQuery(query_msg, time::precise_time_ns()), + ReflowReason::Query, + ) } pub fn layout(&self) -> &LayoutRPC { @@ -1533,22 +1651,18 @@ impl Window { } pub fn scroll_offset_query(&self, node: &Node) -> Vector2D<f32> { - if let Some(scroll_offset) = self.scroll_offsets - .borrow() - .get(&node.to_untrusted_node_address()) { - return *scroll_offset + if let Some(scroll_offset) = self + .scroll_offsets + .borrow() + .get(&node.to_untrusted_node_address()) + { + return *scroll_offset; } Vector2D::new(0.0, 0.0) } // https://drafts.csswg.org/cssom-view/#element-scrolling-members - pub fn scroll_node( - &self, - node: &Node, - x_: f64, - y_: f64, - behavior: ScrollBehavior - ) { + pub fn scroll_node(&self, node: &Node, x_: f64, y_: f64, behavior: ScrollBehavior) { if !self.layout_reflow(QueryMsg::NodeScrollIdQuery(node.to_trusted_node_address())) { return; } @@ -1556,23 +1670,29 @@ impl Window { // The scroll offsets are immediatly updated since later calls // to topScroll and others may access the properties before // webrender has a chance to update the offsets. - self.scroll_offsets.borrow_mut().insert(node.to_untrusted_node_address(), - Vector2D::new(x_ as f32, y_ as f32)); + self.scroll_offsets.borrow_mut().insert( + node.to_untrusted_node_address(), + Vector2D::new(x_ as f32, y_ as f32), + ); let NodeScrollIdResponse(scroll_id) = self.layout_rpc.node_scroll_id(); // Step 12 - self.perform_a_scroll(x_.to_f32().unwrap_or(0.0f32), - y_.to_f32().unwrap_or(0.0f32), - scroll_id, - behavior, - None); + self.perform_a_scroll( + x_.to_f32().unwrap_or(0.0f32), + y_.to_f32().unwrap_or(0.0f32), + scroll_id, + behavior, + None, + ); } - pub fn resolved_style_query(&self, - element: TrustedNodeAddress, - pseudo: Option<PseudoElement>, - property: PropertyId) -> DOMString { + pub fn resolved_style_query( + &self, + element: TrustedNodeAddress, + pseudo: Option<PseudoElement>, + property: PropertyId, + ) -> DOMString { if !self.layout_reflow(QueryMsg::ResolvedStyleQuery(element, pseudo, property)) { return DOMString::new(); } @@ -1581,7 +1701,10 @@ impl Window { } #[allow(unsafe_code)] - pub fn offset_parent_query(&self, node: TrustedNodeAddress) -> (Option<DomRoot<Element>>, Rect<Au>) { + pub fn offset_parent_query( + &self, + node: TrustedNodeAddress, + ) -> (Option<DomRoot<Element>>, Rect<Au>) { if !self.layout_reflow(QueryMsg::OffsetParentQuery(node)) { return (None, Rect::zero()); } @@ -1598,7 +1721,7 @@ impl Window { pub fn style_query(&self, node: TrustedNodeAddress) -> Option<servo_arc::Arc<ComputedValues>> { if !self.layout_reflow(QueryMsg::StyleQuery(node)) { - return None + return None; } self.layout_rpc.style().0 } @@ -1606,7 +1729,7 @@ impl Window { pub fn text_index_query( &self, node: TrustedNodeAddress, - point_in_node: Point2D<f32> + point_in_node: Point2D<f32>, ) -> TextIndexResponse { if !self.layout_reflow(QueryMsg::TextIndexQuery(node, point_in_node)) { return TextIndexResponse(None); @@ -1636,8 +1759,13 @@ impl Window { let _ = fs::remove_dir_all(&path); match fs::create_dir_all(&path) { Ok(_) => { - *self.unminified_js_dir.borrow_mut() = Some(path.into_os_string().into_string().unwrap()); - debug!("Created folder for {:?} unminified scripts {:?}", host, self.unminified_js_dir.borrow()); + *self.unminified_js_dir.borrow_mut() = + Some(path.into_os_string().into_string().unwrap()); + debug!( + "Created folder for {:?} unminified scripts {:?}", + host, + self.unminified_js_dir.borrow() + ); }, Err(_) => warn!("Could not create unminified dir for {:?}", host), } @@ -1645,21 +1773,27 @@ impl Window { } /// Commence a new URL load which will either replace this window or scroll to a fragment. - pub fn load_url(&self, url: ServoUrl, replace: bool, force_reload: bool, - referrer_policy: Option<ReferrerPolicy>) { + pub fn load_url( + &self, + url: ServoUrl, + replace: bool, + force_reload: bool, + referrer_policy: Option<ReferrerPolicy>, + ) { let doc = self.Document(); let referrer_policy = referrer_policy.or(doc.get_referrer_policy()); // https://html.spec.whatwg.org/multipage/#navigating-across-documents - if !force_reload && url.as_url()[..Position::AfterQuery] == - doc.url().as_url()[..Position::AfterQuery] { - // Step 6 - if let Some(fragment) = url.fragment() { - self.send_to_constellation(ScriptMsg::NavigatedToFragment(url.clone(), replace)); - doc.check_and_scroll_fragment(fragment); - let this = Trusted::new(self); - let old_url = doc.url().into_string(); - let new_url = url.clone().into_string(); - let task = task!(hashchange_event: move || { + if !force_reload && + url.as_url()[..Position::AfterQuery] == doc.url().as_url()[..Position::AfterQuery] + { + // Step 6 + if let Some(fragment) = url.fragment() { + self.send_to_constellation(ScriptMsg::NavigatedToFragment(url.clone(), replace)); + doc.check_and_scroll_fragment(fragment); + let this = Trusted::new(self); + let old_url = doc.url().into_string(); + let new_url = url.clone().into_string(); + let task = task!(hashchange_event: move || { let this = this.root(); let event = HashChangeEvent::new( &this, @@ -1670,16 +1804,19 @@ impl Window { new_url); event.upcast::<Event>().fire(this.upcast::<EventTarget>()); }); - // FIXME(nox): Why are errors silenced here? - let _ = self.script_chan.send(CommonScriptMsg::Task( - ScriptThreadEventCategory::DomEvent, - Box::new(self.task_canceller(TaskSourceName::DOMManipulation).wrap_task(task)), - self.pipeline_id(), - TaskSourceName::DOMManipulation, - )); - doc.set_url(url.clone()); - return - } + // FIXME(nox): Why are errors silenced here? + let _ = self.script_chan.send(CommonScriptMsg::Task( + ScriptThreadEventCategory::DomEvent, + Box::new( + self.task_canceller(TaskSourceName::DOMManipulation) + .wrap_task(task), + ), + self.pipeline_id(), + TaskSourceName::DOMManipulation, + )); + doc.set_url(url.clone()); + return; + } } let pipeline_id = self.upcast::<GlobalScope>().pipeline_id(); @@ -1696,11 +1833,13 @@ impl Window { // Step 7 if doc.prompt_to_unload(false) { - self.main_thread_script_chan().send( - MainThreadScriptMsg::Navigate(pipeline_id, - LoadData::new(url, Some(pipeline_id), referrer_policy, Some(doc.url())), replace)).unwrap(); + self.main_thread_script_chan() + .send(MainThreadScriptMsg::Navigate( + pipeline_id, + LoadData::new(url, Some(pipeline_id), referrer_policy, Some(doc.url())), + replace, + )).unwrap(); }; - } pub fn handle_fire_timer(&self, timer_id: TimerEventId) { @@ -1733,7 +1872,8 @@ impl Window { } pub fn add_pending_reflow(&self) { - self.pending_reflow_count.set(self.pending_reflow_count.get() + 1); + self.pending_reflow_count + .set(self.pending_reflow_count.get() + 1); } pub fn set_resize_event(&self, event: WindowSizeData, event_type: WindowSizeType) { @@ -1753,9 +1893,10 @@ impl Window { // so that we don't collect display list items for areas too far outside the viewport, // but also don't trigger reflows every time the viewport changes. static VIEWPORT_EXPANSION: f32 = 2.0; // 2 lengths on each side plus original length is 5 total. - let proposed_clip_rect = f32_rect_to_au_rect( - viewport.inflate(viewport.size.width * VIEWPORT_EXPANSION, - viewport.size.height * VIEWPORT_EXPANSION)); + let proposed_clip_rect = f32_rect_to_au_rect(viewport.inflate( + viewport.size.width * VIEWPORT_EXPANSION, + viewport.size.height * VIEWPORT_EXPANSION, + )); let clip_rect = self.page_clip_rect.get(); if proposed_clip_rect == clip_rect { return false; @@ -1812,11 +1953,15 @@ impl Window { sender.send(Some(marker)).unwrap(); } - pub fn set_devtools_timeline_markers(&self, - markers: Vec<TimelineMarkerType>, - reply: IpcSender<Option<TimelineMarker>>) { + pub fn set_devtools_timeline_markers( + &self, + markers: Vec<TimelineMarkerType>, + reply: IpcSender<Option<TimelineMarker>>, + ) { *self.devtools_marker_sender.borrow_mut() = Some(reply); - self.devtools_markers.borrow_mut().extend(markers.into_iter()); + self.devtools_markers + .borrow_mut() + .extend(markers.into_iter()); } pub fn drop_devtools_timeline_markers(&self, markers: Vec<TimelineMarkerType>) { @@ -1854,11 +1999,14 @@ impl Window { }); // Sending change events for all changed Media Queries for mql in mql_list.iter() { - let event = MediaQueryListEvent::new(&mql.global(), - atom!("change"), - false, false, - mql.Media(), - mql.Matches()); + let event = MediaQueryListEvent::new( + &mql.global(), + atom!("change"), + false, + false, + mql.Media(), + mql.Matches(), + ); event.upcast::<Event>().fire(mql.upcast::<EventTarget>()); } self.Document().react_to_environment_changes(); @@ -2015,9 +2163,7 @@ impl Window { exists_mut_observer: Cell::new(false), }); - unsafe { - WindowBinding::Wrap(runtime.cx(), win) - } + unsafe { WindowBinding::Wrap(runtime.cx(), win) } } pub fn pipeline_id(&self) -> Option<PipelineId> { @@ -2026,10 +2172,16 @@ impl Window { } fn should_move_clip_rect(clip_rect: Rect<Au>, new_viewport: Rect<f32>) -> bool { - let clip_rect = Rect::new(Point2D::new(clip_rect.origin.x.to_f32_px(), - clip_rect.origin.y.to_f32_px()), - Size2D::new(clip_rect.size.width.to_f32_px(), - clip_rect.size.height.to_f32_px())); + let clip_rect = Rect::new( + Point2D::new( + clip_rect.origin.x.to_f32_px(), + clip_rect.origin.y.to_f32_px(), + ), + Size2D::new( + clip_rect.size.width.to_f32_px(), + clip_rect.size.height.to_f32_px(), + ), + ); // We only need to move the clip rect if the viewport is getting near the edge of // our preexisting clip rect. We use half of the size of the viewport as a heuristic @@ -2038,9 +2190,9 @@ fn should_move_clip_rect(clip_rect: Rect<Au>, new_viewport: Rect<f32>) -> bool { let viewport_scroll_margin = new_viewport.size * VIEWPORT_SCROLL_MARGIN_SIZE; (clip_rect.origin.x - new_viewport.origin.x).abs() <= viewport_scroll_margin.width || - (clip_rect.max_x() - new_viewport.max_x()).abs() <= viewport_scroll_margin.width || - (clip_rect.origin.y - new_viewport.origin.y).abs() <= viewport_scroll_margin.height || - (clip_rect.max_y() - new_viewport.max_y()).abs() <= viewport_scroll_margin.height + (clip_rect.max_x() - new_viewport.max_x()).abs() <= viewport_scroll_margin.width || + (clip_rect.origin.y - new_viewport.origin.y).abs() <= viewport_scroll_margin.height || + (clip_rect.max_y() - new_viewport.max_y()).abs() <= viewport_scroll_margin.height } fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal, reason: &ReflowReason) { @@ -2134,7 +2286,10 @@ impl Window { // TODO: When switching to the right task source, update the task_canceller call too. let _ = self.script_chan.send(CommonScriptMsg::Task( ScriptThreadEventCategory::DomEvent, - Box::new(self.task_canceller(TaskSourceName::DOMManipulation).wrap_task(task)), + Box::new( + self.task_canceller(TaskSourceName::DOMManipulation) + .wrap_task(task), + ), self.pipeline_id(), TaskSourceName::DOMManipulation, )); |