From ff4cd4af960b2f0c506cf3a53336d4ffe56ac988 Mon Sep 17 00:00:00 2001 From: Jonathan Schwender <55576758+jschwe@users.noreply.github.com> Date: Fri, 14 Jun 2024 08:26:35 +0200 Subject: [PATCH] Split servoshell into Desktop and common part (#32457) * servoshell: Move desktop files Move files related to winit into a desktop module. This is a preparation to merge the android and ohos apps into servoshell. * servoshell: Format imports * servoshell: Move panic hook into separate file * servoshell: Move desktop main * Consider ohos as not desktop * servoshell: Adjust dependencies for shared code * servoshell: Remove native-bluetooth from default features There currently is no good way to have target specific default features. * Rename desktop_main.rs to cli.rs * Remove todo --- Cargo.lock | 1 + ports/servoshell/Cargo.toml | 28 +-- ports/servoshell/{ => desktop}/app.rs | 13 +- ports/servoshell/desktop/cli.rs | 104 ++++++++++++ ports/servoshell/{ => desktop}/egui_glue.rs | 0 ports/servoshell/{ => desktop}/embedder.rs | 0 ports/servoshell/{ => desktop}/events_loop.rs | 0 ports/servoshell/{ => desktop}/geometry.rs | 0 .../servoshell/{ => desktop}/headed_window.rs | 10 +- .../{ => desktop}/headless_window.rs | 4 +- ports/servoshell/{ => desktop}/keyutils.rs | 0 ports/servoshell/{ => desktop}/minibrowser.rs | 10 +- ports/servoshell/desktop/mod.rs | 19 +++ ports/servoshell/{ => desktop}/tracing.rs | 10 +- ports/servoshell/{ => desktop}/webview.rs | 5 +- .../servoshell/{ => desktop}/window_trait.rs | 2 +- ports/servoshell/lib.rs | 159 ++---------------- ports/servoshell/panic_hook.rs | 47 ++++++ 18 files changed, 233 insertions(+), 179 deletions(-) rename ports/servoshell/{ => desktop}/app.rs (98%) create mode 100644 ports/servoshell/desktop/cli.rs rename ports/servoshell/{ => desktop}/egui_glue.rs (100%) rename ports/servoshell/{ => desktop}/embedder.rs (100%) rename ports/servoshell/{ => desktop}/events_loop.rs (100%) rename ports/servoshell/{ => desktop}/geometry.rs (100%) rename ports/servoshell/{ => desktop}/headed_window.rs (98%) rename ports/servoshell/{ => desktop}/headless_window.rs (98%) rename ports/servoshell/{ => desktop}/keyutils.rs (100%) rename ports/servoshell/{ => desktop}/minibrowser.rs (98%) create mode 100644 ports/servoshell/desktop/mod.rs rename ports/servoshell/{ => desktop}/tracing.rs (96%) rename ports/servoshell/{ => desktop}/webview.rs (99%) rename ports/servoshell/{ => desktop}/window_trait.rs (98%) create mode 100644 ports/servoshell/panic_hook.rs diff --git a/Cargo.lock b/Cargo.lock index 30b04455ca9..d9a52913cae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5688,6 +5688,7 @@ dependencies = [ "gleam", "glow", "image", + "ipc-channel", "keyboard-types", "lazy_static", "libc", diff --git a/ports/servoshell/Cargo.toml b/ports/servoshell/Cargo.toml index 386c90c6137..f465ca186b0 100644 --- a/ports/servoshell/Cargo.toml +++ b/ports/servoshell/Cargo.toml @@ -35,7 +35,7 @@ ProductName = "Servo" [features] debugmozjs = ["libservo/debugmozjs"] -default = ["max_log_level", "native-bluetooth", "webdriver"] +default = ["max_log_level", "webdriver"] jitspew = ["libservo/jitspew"] js_backtrace = ["libservo/js_backtrace"] max_log_level = ["log/release_max_level_info"] @@ -52,24 +52,33 @@ xr-profile = ["libservo/xr-profile"] [dependencies] # For optional feature servo_allocator/use-system-allocator servo_allocator = { path = "../../components/allocator" } +libc = { workspace = true } +libservo = { path = "../../components/servo" } +cfg-if = { workspace = true } +log = { workspace = true } +url = { workspace = true } +lazy_static = { workspace = true } + [target.'cfg(not(target_os = "android"))'.dependencies] -arboard = { version = "3" } backtrace = { workspace = true } -cfg-if = { workspace = true } +getopts = { workspace = true } + +[target.'cfg(target_env = "ohos")'.dependencies] +# force inprocess, until libc-rs is updated to include `shm_open` and unlink. +ipc-channel = { workspace = true, features = ["force-inprocess"] } + + +[target.'cfg(not(any(target_os = "android", target_env = "ohos")))'.dependencies] +arboard = { version = "3" } egui = { version = "0.26.2" } egui_glow = { version = "0.26.2", features = ["winit"] } egui-winit = { version = "0.26.2", default-features = false, features = ["clipboard", "wayland"] } euclid = { workspace = true } -getopts = { workspace = true } gilrs = "0.10.7" gleam = { workspace = true } glow = "0.13.1" keyboard-types = { workspace = true } -lazy_static = { workspace = true } -libc = { workspace = true } -libservo = { path = "../../components/servo" } -log = { workspace = true } raw-window-handle = "0.6" servo-media = { workspace = true } shellwords = "1.0.0" @@ -77,9 +86,8 @@ surfman = { workspace = true, features = ["sm-x11", "sm-raw-window-handle-06"] } tinyfiledialogs = "3.0" webxr = { git = "https://github.com/servo/webxr", features = ["ipc", "glwindow", "headless"] } winit = "0.29.10" -url = { workspace = true } -[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies] +[target.'cfg(any(all(target_os = "linux", not(target_env = "ohos")), target_os = "windows"))'.dependencies] image = { workspace = true } [target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies] diff --git a/ports/servoshell/app.rs b/ports/servoshell/desktop/app.rs similarity index 98% rename from ports/servoshell/app.rs rename to ports/servoshell/desktop/app.rs index 5176b59e260..9cdf1eb8c08 100644 --- a/ports/servoshell/app.rs +++ b/ports/servoshell/desktop/app.rs @@ -23,13 +23,14 @@ use winit::event::WindowEvent; use winit::event_loop::EventLoopWindowTarget; use winit::window::WindowId; -use crate::embedder::EmbedderCallbacks; -use crate::events_loop::{EventsLoop, WakerEvent}; -use crate::minibrowser::Minibrowser; +use super::events_loop::{EventsLoop, WakerEvent}; +use super::minibrowser::Minibrowser; +use super::webview::WebViewManager; +use super::{headed_window, headless_window}; +use crate::desktop::embedder::EmbedderCallbacks; +use crate::desktop::tracing::trace_winit_event; +use crate::desktop::window_trait::WindowPortsMethods; use crate::parser::get_default_url; -use crate::webview::WebViewManager; -use crate::window_trait::WindowPortsMethods; -use crate::{headed_window, headless_window}; pub struct App { servo: Option>, diff --git a/ports/servoshell/desktop/cli.rs b/ports/servoshell/desktop/cli.rs new file mode 100644 index 00000000000..5eb8ad7a3aa --- /dev/null +++ b/ports/servoshell/desktop/cli.rs @@ -0,0 +1,104 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use std::{env, panic, process}; + +use getopts::Options; +use log::error; +use servo::config::opts::{self, ArgumentParsingResult}; +use servo::servo_config::pref; + +use crate::desktop::app::App; +use crate::panic_hook; + +pub fn main() { + crate::crash_handler::install(); + + crate::resources::init(); + + // Parse the command line options and store them globally + let args: Vec = env::args().collect(); + let mut opts = Options::new(); + opts.optflag( + "", + "clean-shutdown", + "Do not shutdown until all threads have finished (macos only)", + ); + opts.optflag("b", "no-native-titlebar", "Do not use native titlebar"); + opts.optopt("", "device-pixel-ratio", "Device pixels per px", ""); + opts.optopt( + "u", + "user-agent", + "Set custom user agent string (or ios / android / desktop for platform default)", + "NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)", + ); + opts.optmulti( + "", + "pref", + "A preference to set to enable", + "dom.bluetooth.enabled", + ); + opts.optmulti( + "", + "pref", + "A preference to set to disable", + "dom.webgpu.enabled=false", + ); + + let opts_matches; + let content_process_token; + + match opts::from_cmdline_args(opts, &args) { + ArgumentParsingResult::ContentProcess(matches, token) => { + opts_matches = matches; + content_process_token = Some(token); + }, + ArgumentParsingResult::ChromeProcess(matches) => { + opts_matches = matches; + content_process_token = None; + }, + }; + + crate::prefs::register_user_prefs(&opts_matches); + + // TODO: once log-panics is released, can this be replaced by + // log_panics::init()? + panic::set_hook(Box::new(panic_hook::panic_hook)); + + if let Some(token) = content_process_token { + return servo::run_content_process(token); + } + + if opts::get().is_printing_version { + println!("{}", crate::servo_version()); + process::exit(0); + } + + let clean_shutdown = opts_matches.opt_present("clean-shutdown"); + let do_not_use_native_titlebar = + opts_matches.opt_present("no-native-titlebar") || !(pref!(shell.native_titlebar.enabled)); + let device_pixel_ratio_override = opts_matches.opt_str("device-pixel-ratio").map(|dppx_str| { + dppx_str.parse().unwrap_or_else(|err| { + error!("Error parsing option: --device-pixel-ratio ({})", err); + process::exit(1); + }) + }); + + let user_agent = opts_matches.opt_str("u"); + + let url_opt = if !opts_matches.free.is_empty() { + Some(&opts_matches.free[0][..]) + } else { + None + }; + + App::run( + do_not_use_native_titlebar, + device_pixel_ratio_override, + user_agent, + url_opt.map(|s| s.to_string()), + ); + + crate::platform::deinit(clean_shutdown) +} diff --git a/ports/servoshell/egui_glue.rs b/ports/servoshell/desktop/egui_glue.rs similarity index 100% rename from ports/servoshell/egui_glue.rs rename to ports/servoshell/desktop/egui_glue.rs diff --git a/ports/servoshell/embedder.rs b/ports/servoshell/desktop/embedder.rs similarity index 100% rename from ports/servoshell/embedder.rs rename to ports/servoshell/desktop/embedder.rs diff --git a/ports/servoshell/events_loop.rs b/ports/servoshell/desktop/events_loop.rs similarity index 100% rename from ports/servoshell/events_loop.rs rename to ports/servoshell/desktop/events_loop.rs diff --git a/ports/servoshell/geometry.rs b/ports/servoshell/desktop/geometry.rs similarity index 100% rename from ports/servoshell/geometry.rs rename to ports/servoshell/desktop/geometry.rs diff --git a/ports/servoshell/headed_window.rs b/ports/servoshell/desktop/headed_window.rs similarity index 98% rename from ports/servoshell/headed_window.rs rename to ports/servoshell/desktop/headed_window.rs index 8cec4d95891..3cbbf3a8d92 100644 --- a/ports/servoshell/headed_window.rs +++ b/ports/servoshell/desktop/headed_window.rs @@ -32,10 +32,10 @@ use winit::keyboard::{Key as LogicalKey, ModifiersState, NamedKey}; #[cfg(any(target_os = "linux", target_os = "windows"))] use winit::window::Icon; -use crate::events_loop::{EventsLoop, WakerEvent}; -use crate::geometry::{winit_position_to_euclid_point, winit_size_to_euclid_size}; -use crate::keyutils::keyboard_event_from_winit; -use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT}; +use super::events_loop::{EventsLoop, WakerEvent}; +use super::geometry::{winit_position_to_euclid_point, winit_size_to_euclid_size}; +use super::keyutils::keyboard_event_from_winit; +use super::window_trait::{WindowPortsMethods, LINE_HEIGHT}; pub struct Window { winit_window: winit::window::Window, @@ -103,7 +103,7 @@ impl Window { #[cfg(any(target_os = "linux", target_os = "windows"))] { - let icon_bytes = include_bytes!("../../resources/servo_64.png"); + let icon_bytes = include_bytes!("../../../resources/servo_64.png"); winit_window.set_window_icon(Some(load_icon(icon_bytes))); } diff --git a/ports/servoshell/headless_window.rs b/ports/servoshell/desktop/headless_window.rs similarity index 98% rename from ports/servoshell/headless_window.rs rename to ports/servoshell/desktop/headless_window.rs index 1420f45c080..421332d9b50 100644 --- a/ports/servoshell/headless_window.rs +++ b/ports/servoshell/desktop/headless_window.rs @@ -20,8 +20,8 @@ use servo::webrender_api::units::{DeviceIntRect, DeviceIntSize}; use servo::webrender_traits::RenderingContext; use surfman::{Connection, Context, Device, SurfaceType}; -use crate::events_loop::WakerEvent; -use crate::window_trait::WindowPortsMethods; +use super::events_loop::WakerEvent; +use crate::desktop::window_trait::WindowPortsMethods; pub struct Window { rendering_context: RenderingContext, diff --git a/ports/servoshell/keyutils.rs b/ports/servoshell/desktop/keyutils.rs similarity index 100% rename from ports/servoshell/keyutils.rs rename to ports/servoshell/desktop/keyutils.rs diff --git a/ports/servoshell/minibrowser.rs b/ports/servoshell/desktop/minibrowser.rs similarity index 98% rename from ports/servoshell/minibrowser.rs rename to ports/servoshell/desktop/minibrowser.rs index d2646cf695b..4c25512a5b3 100644 --- a/ports/servoshell/minibrowser.rs +++ b/ports/servoshell/desktop/minibrowser.rs @@ -25,12 +25,12 @@ use servo::style_traits::DevicePixel; use servo::webrender_traits::RenderingContext; use winit::event::{ElementState, MouseButton}; -use crate::egui_glue::EguiGlow; -use crate::events_loop::EventsLoop; -use crate::geometry::winit_position_to_euclid_point; +use super::egui_glue::EguiGlow; +use super::events_loop::EventsLoop; +use super::geometry::winit_position_to_euclid_point; +use super::webview::{LoadStatus, WebViewManager}; +use super::window_trait::WindowPortsMethods; use crate::parser::location_bar_input_to_url; -use crate::webview::{LoadStatus, WebViewManager}; -use crate::window_trait::WindowPortsMethods; pub struct Minibrowser { pub context: EguiGlow, diff --git a/ports/servoshell/desktop/mod.rs b/ports/servoshell/desktop/mod.rs new file mode 100644 index 00000000000..919522124af --- /dev/null +++ b/ports/servoshell/desktop/mod.rs @@ -0,0 +1,19 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! Contains files specific to the servoshell app for Desktop systems. + +pub(crate) mod app; +pub(crate) mod cli; +mod egui_glue; +mod embedder; +pub(crate) mod events_loop; +pub mod geometry; +mod headed_window; +mod headless_window; +mod keyutils; +mod minibrowser; +mod tracing; +mod webview; +mod window_trait; diff --git a/ports/servoshell/tracing.rs b/ports/servoshell/desktop/tracing.rs similarity index 96% rename from ports/servoshell/tracing.rs rename to ports/servoshell/desktop/tracing.rs index cc7d603191a..59c07105c94 100644 --- a/ports/servoshell/tracing.rs +++ b/ports/servoshell/desktop/tracing.rs @@ -18,7 +18,7 @@ macro_rules! trace_winit_event { // This macro only exists to put the docs in the same file as the target prefix, // so the macro definition is always the same. ($event:expr, $($rest:tt)+) => { - ::log::trace!(target: $crate::tracing::LogTarget::log_target(&$event), $($rest)+) + ::log::trace!(target: $crate::desktop::tracing::LogTarget::log_target(&$event), $($rest)+) }; } @@ -32,7 +32,7 @@ macro_rules! trace_embedder_msg { // This macro only exists to put the docs in the same file as the target prefix, // so the macro definition is always the same. ($event:expr, $($rest:tt)+) => { - ::log::trace!(target: $crate::tracing::LogTarget::log_target(&$event), $($rest)+) + ::log::trace!(target: $crate::desktop::tracing::LogTarget::log_target(&$event), $($rest)+) }; } @@ -46,10 +46,12 @@ macro_rules! trace_embedder_event { // This macro only exists to put the docs in the same file as the target prefix, // so the macro definition is always the same. ($event:expr, $($rest:tt)+) => { - ::log::trace!(target: $crate::tracing::LogTarget::log_target(&$event), $($rest)+) + ::log::trace!(target: $crate::desktop::tracing::LogTarget::log_target(&$event), $($rest)+) }; } +pub(crate) use {trace_embedder_event, trace_embedder_msg, trace_winit_event}; + /// Get the log target for an event, as a static string. pub(crate) trait LogTarget { fn log_target(&self) -> &'static str; @@ -57,7 +59,7 @@ pub(crate) trait LogTarget { mod from_winit { use super::LogTarget; - use crate::events_loop::WakerEvent; + use crate::desktop::events_loop::WakerEvent; macro_rules! target { ($($name:literal)+) => { diff --git a/ports/servoshell/webview.rs b/ports/servoshell/desktop/webview.rs similarity index 99% rename from ports/servoshell/webview.rs rename to ports/servoshell/desktop/webview.rs index b20214646ba..ec6ab2fbf0a 100644 --- a/ports/servoshell/webview.rs +++ b/ports/servoshell/desktop/webview.rs @@ -31,9 +31,10 @@ use servo::webrender_api::units::DeviceRect; use servo::webrender_api::ScrollLocation; use tinyfiledialogs::{self, MessageBoxIcon, OkCancel, YesNo}; -use crate::keyutils::{CMD_OR_ALT, CMD_OR_CONTROL}; +use super::keyutils::{CMD_OR_ALT, CMD_OR_CONTROL}; +use super::window_trait::{WindowPortsMethods, LINE_HEIGHT}; +use crate::desktop::tracing::{trace_embedder_event, trace_embedder_msg}; use crate::parser::location_bar_input_to_url; -use crate::window_trait::{WindowPortsMethods, LINE_HEIGHT}; pub struct WebViewManager { current_url: Option, diff --git a/ports/servoshell/window_trait.rs b/ports/servoshell/desktop/window_trait.rs similarity index 98% rename from ports/servoshell/window_trait.rs rename to ports/servoshell/desktop/window_trait.rs index b7bf9cba717..38aa52a8c71 100644 --- a/ports/servoshell/window_trait.rs +++ b/ports/servoshell/desktop/window_trait.rs @@ -13,7 +13,7 @@ use servo::servo_geometry::DeviceIndependentPixel; use servo::style_traits::DevicePixel; use servo::webrender_api::units::{DeviceIntPoint, DeviceIntSize}; -use crate::events_loop::WakerEvent; +use super::events_loop::WakerEvent; // This should vary by zoom level and maybe actual text size (focused or under cursor) pub const LINE_HEIGHT: f32 = 38.0; diff --git a/ports/servoshell/lib.rs b/ports/servoshell/lib.rs index 842b3abfe46..512d4522612 100644 --- a/ports/servoshell/lib.rs +++ b/ports/servoshell/lib.rs @@ -9,28 +9,17 @@ #[macro_use] extern crate sig; -#[macro_use] -mod tracing; - #[cfg(test)] mod test; -mod app; mod backtrace; mod crash_handler; -mod egui_glue; -mod embedder; -mod events_loop; -mod geometry; -mod headed_window; -mod headless_window; -mod keyutils; -mod minibrowser; +#[cfg(not(any(target_os = "android", target_env = "ohos")))] +pub(crate) mod desktop; +mod panic_hook; mod parser; mod prefs; mod resources; -mod webview; -mod window_trait; pub mod platform { #[cfg(target_os = "macos")] @@ -43,140 +32,22 @@ pub mod platform { pub fn deinit(_clean_shutdown: bool) {} } -use std::io::Write; -use std::{env, panic, process, thread}; - -use getopts::Options; -use log::{error, warn}; -use servo::config::opts::{self, ArgumentParsingResult}; -use servo::servo_config::pref; - -use crate::app::App; - +#[cfg(not(any(target_os = "android", target_env = "ohos")))] pub fn main() { - crate::crash_handler::install(); + desktop::cli::main() +} - crate::resources::init(); - - // Parse the command line options and store them globally - let args: Vec = env::args().collect(); - let mut opts = Options::new(); - opts.optflag( - "", - "clean-shutdown", - "Do not shutdown until all threads have finished (macos only)", - ); - opts.optflag("b", "no-native-titlebar", "Do not use native titlebar"); - opts.optopt("", "device-pixel-ratio", "Device pixels per px", ""); - opts.optopt( - "u", - "user-agent", - "Set custom user agent string (or ios / android / desktop for platform default)", - "NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)", - ); - opts.optmulti( - "", - "pref", - "A preference to set to enable", - "dom.bluetooth.enabled", - ); - opts.optmulti( - "", - "pref", - "A preference to set to disable", - "dom.webgpu.enabled=false", +#[cfg(target_os = "android")] +pub fn main() { + println!( + "Cannot start /ports/servoshell/ on Android. \ + Use /support/android/apk/ + /ports/jniapi/ instead" ); +} - let opts_matches; - let content_process_token; - - match opts::from_cmdline_args(opts, &args) { - ArgumentParsingResult::ContentProcess(matches, token) => { - opts_matches = matches; - content_process_token = Some(token); - }, - ArgumentParsingResult::ChromeProcess(matches) => { - opts_matches = matches; - content_process_token = None; - }, - }; - - crate::prefs::register_user_prefs(&opts_matches); - - // TODO: once log-panics is released, can this be replaced by - // log_panics::init()? - panic::set_hook(Box::new(|info| { - warn!("Panic hook called."); - let msg = match info.payload().downcast_ref::<&'static str>() { - Some(s) => *s, - None => match info.payload().downcast_ref::() { - Some(s) => &**s, - None => "Box", - }, - }; - let current_thread = thread::current(); - let name = current_thread.name().unwrap_or(""); - let stderr = std::io::stderr(); - let mut stderr = stderr.lock(); - if let Some(location) = info.location() { - let _ = writeln!( - &mut stderr, - "{} (thread {}, at {}:{})", - msg, - name, - location.file(), - location.line() - ); - } else { - let _ = writeln!(&mut stderr, "{} (thread {})", msg, name); - } - if env::var("RUST_BACKTRACE").is_ok() { - let _ = crate::backtrace::print(&mut stderr); - } - drop(stderr); - - if opts::get().hard_fail && !opts::get().multiprocess { - std::process::exit(1); - } - - error!("{}", msg); - })); - - if let Some(token) = content_process_token { - return servo::run_content_process(token); - } - - if opts::get().is_printing_version { - println!("{}", servo_version()); - process::exit(0); - } - - let clean_shutdown = opts_matches.opt_present("clean-shutdown"); - let do_not_use_native_titlebar = - opts_matches.opt_present("no-native-titlebar") || !(pref!(shell.native_titlebar.enabled)); - let device_pixel_ratio_override = opts_matches.opt_str("device-pixel-ratio").map(|dppx_str| { - dppx_str.parse().unwrap_or_else(|err| { - error!("Error parsing option: --device-pixel-ratio ({})", err); - process::exit(1); - }) - }); - - let user_agent = opts_matches.opt_str("u"); - - let url_opt = if !opts_matches.free.is_empty() { - Some(&opts_matches.free[0][..]) - } else { - None - }; - - App::run( - do_not_use_native_titlebar, - device_pixel_ratio_override, - user_agent, - url_opt.map(|s| s.to_string()), - ); - - crate::platform::deinit(clean_shutdown) +#[cfg(target_env = "ohos")] +pub fn main() { + println!("You shouldn't start /ports/servoshell/ on OpenHarmony."); } pub fn servo_version() -> String { diff --git a/ports/servoshell/panic_hook.rs b/ports/servoshell/panic_hook.rs new file mode 100644 index 00000000000..c71f27d2dfd --- /dev/null +++ b/ports/servoshell/panic_hook.rs @@ -0,0 +1,47 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use std::io::Write; +use std::panic::PanicInfo; +use std::{env, thread}; + +use log::{error, warn}; +use servo::config::opts; + +pub(crate) fn panic_hook(info: &PanicInfo) { + warn!("Panic hook called."); + let msg = match info.payload().downcast_ref::<&'static str>() { + Some(s) => *s, + None => match info.payload().downcast_ref::() { + Some(s) => &**s, + None => "Box", + }, + }; + let current_thread = thread::current(); + let name = current_thread.name().unwrap_or(""); + let stderr = std::io::stderr(); + let mut stderr = stderr.lock(); + if let Some(location) = info.location() { + let _ = writeln!( + &mut stderr, + "{} (thread {}, at {}:{})", + msg, + name, + location.file(), + location.line() + ); + } else { + let _ = writeln!(&mut stderr, "{} (thread {})", msg, name); + } + if env::var("RUST_BACKTRACE").is_ok() { + let _ = crate::backtrace::print(&mut stderr); + } + drop(stderr); + + if opts::get().hard_fail && !opts::get().multiprocess { + std::process::exit(1); + } + + error!("{}", msg); +}