Skip to content

Commit

Permalink
Register panic handler to receive and log unhandled exceptions to the…
Browse files Browse the repository at this point in the history
… browser console.
  • Loading branch information
maaku committed Jul 16, 2024
1 parent 1988473 commit 9e90c8b
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 8 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions crates/app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ authors = ["Machine Phase Systems <hello@machinephase.systems>"]
license = "MPL-2.0"
edition = "2021"

[features]
default = ["console_error_panic_hook"]

[dependencies]
# rust
readonly = { workspace = true }

[target.'cfg(target_family = "wasm")'.dependencies]
# Web platform support
console_error_panic_hook = { version = "0.1.7", optional = true }
32 changes: 25 additions & 7 deletions crates/app/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// 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 <http://mozilla.org/MPL/2.0/>.

use crate::Plugin;
use crate::{PanicHandlerPlugin, Plugin};
use core::num::NonZero;
use std::collections::HashSet;

Expand Down Expand Up @@ -66,19 +66,37 @@ pub fn run_once(app: &mut App) -> AppExit {
/// .run();
/// ```
impl App {
/// Creates a new application runner with the given name. The name is used to identify the
/// application in log messages and other diagnostic output, as well as user interface elements
/// in window managers (default window title, application menu name on macOS, etc.). The runner
/// is initialized to [`run_once`], but can be changed with [`App::set_runner`]. The name must
/// be specified, but can later be changed with [`App::set_name`].
pub fn new(name: String) -> Self {
/// Creates a new application runner with the given name, with no default configuration.
/// Depending on your platform, some platform-specific initialization may be required. For a
/// list of the default plugins excluded, see [`App::new`].
pub fn empty(name: String) -> Self {
Self {
name,
runner: Box::new(run_once),
plugins: HashSet::new(),
}
}

/// Creates a new application runner with the given name, initialized with a sensible but
/// minimal list of default plugins for platform support. To initialize a new application
/// runner with absolutely no default configuration behavior, use [`App::empty`].
///
/// The name is used to identify the application in log messages and other diagnostic output, as
/// well as user interface elements in window managers (default window title, application menu
/// name on macOS, etc.). The runner is initialized to [`run_once`], but can be changed with
/// [`App::set_runner`]. The name must be specified, but can later be changed with
/// [`App::set_name`].
///
/// # Current Default Plugins:
///
/// * [`PanicHandlerPlugin`]: Registers a panic hook that logs errors to the Javascript console
/// on web. On other platforms, this plugin does nothing.
pub fn new(name: String) -> Self {
let mut app = Self::empty(name);
app.add_plugin(PanicHandlerPlugin);
app
}

/// Change the name of the application runner, during configuration or at runtime. To read the
/// current application name, do so directly via the [`App::name`] field.
pub fn set_name(&mut self, name: String) -> &mut Self {
Expand Down
6 changes: 5 additions & 1 deletion crates/app/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@
mod app;
pub use app::{run_once, App, AppExit};

mod platform;
mod platform_impl;
pub use platform::PanicHandlerPlugin;

mod plugin;
pub use plugin::Plugin;

/// A module which is typically glob imported.
pub mod prelude {
pub use super::{App, AppExit, Plugin};
pub use super::{App, AppExit, PanicHandlerPlugin, Plugin};
}

// End of File
35 changes: 35 additions & 0 deletions crates/app/src/platform.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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 <http://mozilla.org/MPL/2.0/>.

use crate::{App, Plugin};

/// Application plugin to perform platform-specific initialization. On the web backend, this sets
/// up the console to catch and log unhandled panics. On all other backends, this does nothing. It
/// is a default plugin included in [`App`] instances returned by [`App::new`].
pub struct PanicHandlerPlugin;

/// When added to an [`App`] instance, ensures that any unhandled panics will be logged to the
/// Javascript console on web platforms. Currently performs no other action on other backends.
///
/// ```
/// # use atomcad_app::prelude::*;
/// fn run(app: &mut App) {
/// panic!("Oh no!");
/// }
///
/// App::empty("Panic Handler Plugin".into())
/// .add_plugin(PanicHandlerPlugin)
/// .run();
///
/// // Backtrace will be printed to debug console.
/// ```
impl Plugin for PanicHandlerPlugin {
/// Sets up the panic handler to log errors to the console on the web backend if we are running
/// on WebAssembly, so that panics can be viewed in the browser's debug inspector. Otherwise
/// does nothing.
fn build(&self, _app: &mut App) {
crate::platform_impl::setup_panic_handler();
}
}

// End of File
7 changes: 7 additions & 0 deletions crates/app/src/platform_impl/default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// 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 <http://mozilla.org/MPL/2.0/>.

/// Do nothing on non-web platforms.
pub(crate) fn setup_panic_handler() {}

// End of File
20 changes: 20 additions & 0 deletions crates/app/src/platform_impl/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// 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 <http://mozilla.org/MPL/2.0/>.

// Only web implements any platform-specific application initialization code, at this time. All
// other platforms pull the default implementation, which provides stub plugins that don't do
// anything.

#[cfg(target_family = "wasm")]
mod web;
#[cfg(target_family = "wasm")]
#[allow(unused_imports)]
pub use self::web::*;

#[cfg(not(target_family = "wasm"))]
mod default;
#[cfg(not(target_family = "wasm"))]
#[allow(unused_imports)]
pub use self::default::*;

// End of File
9 changes: 9 additions & 0 deletions crates/app/src/platform_impl/web.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// 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 <http://mozilla.org/MPL/2.0/>.

/// Register the panic hook that logs errors to the Javascript console.
pub(crate) fn setup_panic_handler() {
console_error_panic_hook::set_once();
}

// End of File

0 comments on commit 9e90c8b

Please sign in to comment.