Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.3.0 #4

Merged
merged 4 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 42 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,57 @@ Subheadings to categorize changes are `added, changed, deprecated, removed, fixe

## Unreleased

## 0.2.0
This release has an [MSRV][] of 1.75.

### added
## [0.3.0] - 2024/08/15

This release has an [MSRV][] of 1.75.

### Added

- `set_hook_with` now takes an additional argument, `on_panic_callback` which is triggered automatically on panic. ([#3] by [@simbleau])

### Fixed

- If a panic occurs after the first panic (which can happen in multi-threaded apps, e.g. Bevy games), it will only be logged to stdout. Hence, only the first panic that occurred is preserved. ([#3] by [@simbleau])

## [0.2.0] - 2024/04/15

This release has an [MSRV][] of 1.75.

### Added

- `FORM_TEXTAREA_ID` is now public, which has the element ID of the stack trace text area.
- `FORM_SUBMIT_ID` is now public, which has the element ID of the submit button.

### changed
### Changed

- `set_hook_with` now takes the additional argument of an HTML form structure. The previous, default form can still be used with `web_panic_report::set_default_hook_with`, however requires the new (default) cargo feature: `default-form`. ([#2] by [@simbleau])

- `set_hook_with` now takes the additional argument of an HTML form structure. The previous, default form can still be used with `web_panic_report::set_default_hook_with`, however requires the new (default) cargo feature: `default-form`.
## [0.1.1] - 2024/03/17

## 0.1.1
This release has an [MSRV][] of 1.75.

### changed
### Fixed

- Any patch version of `web-sys` or `wasm-bindgen` can now be used.

## 0.1.0
## [0.1.0] - 2024/03/17

This release has an [MSRV][] of 1.75.

- Initialize release ([@Vrixyz] and [@simbleau])

[@simbleau]: https://github.com/simbleau
[@Vrixyz]: https://github.com/Vrixyz

[#2]: https://github.com/loopystudios/web_panic_report/pull/2
[#3]: https://github.com/loopystudios/web_panic_report/pull/3

[Unreleased]: https://github.com/loopystudios/web_panic_report/compare/v0.3.0...HEAD
[0.3.0]: https://github.com/loopystudios/web_panic_report/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/loopystudios/web_panic_report/compare/v0.1.1...v0.2.0
[0.1.1]: https://github.com/loopystudios/web_panic_report/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/loopystudios/web_panic_report/releases/tag/v0.1.0

- Initialize release
[MSRV]: README.md#minimum-supported-rust-version-msrv
20 changes: 20 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,26 @@ You can also use a custom bug report form. See the [custom example](examples/cus

- [`console_error_panic_hook`](https://github.com/rustwasm/console_error_panic_hook) - Only outputs stack trace to the console.

## Minimum supported Rust Version (MSRV)

This version of Web Panic Report has been verified to compile with **Rust 1.75** and later.

Future versions of Web Panic Report might increase the Rust version requirement.
It will not be treated as a breaking change and as such can even happen with small patch releases.

<details>
<summary>Click here if compiling fails.</summary>

As time has passed, some of Web Panic Report's dependencies could have released versions with a higher Rust requirement.
If you encounter a compilation issue due to a dependency and don't want to upgrade your Rust toolchain, then you could downgrade the dependency.

```sh
# Use the problematic dependency's name and version
cargo update -p package_name --precise 0.1.1
```

</details>

## Community

All Loopy projects and development happens in the [Loopy Discord](https://discord.gg/zrjnQzdjCB). The discord is open to the public.
Expand Down
19 changes: 13 additions & 6 deletions examples/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,17 @@ fn main() {
);

// Set the panic hook at the beginning of your program
web_panic_report::set_hook_with("test-container", my_form, |panic_info| {
web_sys::window()
.unwrap()
.alert_with_message(&panic_info.display.to_string())
.unwrap();
});
web_panic_report::set_hook_with(
"test-container",
my_form,
// No-op on panic
|_| {},
// Submit button will cause a web browser alert
|panic_info| {
web_sys::window()
.unwrap()
.alert_with_message(&panic_info.display.to_string())
.unwrap();
},
);
}
7 changes: 4 additions & 3 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
max_width = 100
# TODO: comment_width = 100 - Wait for this to be stable
# TODO: wrap_comments = true - Wait for this to be stable
use_field_init_shorthand = true
newline_style = "Unix"
# TODO: imports_granularity = "Crate" - Wait for this to be stable.
# TODO: Enable - Currently nightly only :(
# wrap_comments = true
# comment_width = 100
# imports_granularity = "Crate"
2 changes: 1 addition & 1 deletion src/default_form/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ pub fn set_default_hook_with<F>(container_id: impl Into<String>, submit_callback
where
F: Fn(&WasmPanicInfo) + Send + Sync + 'static,
{
crate::set_hook_with(container_id, FORM_HTML, submit_callback)
crate::set_hook_with(container_id, FORM_HTML, |_| {}, submit_callback)
}
79 changes: 48 additions & 31 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::sync::Arc;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use wasm_bindgen::prelude::*;
use web_sys::wasm_bindgen::JsCast;
use web_sys::{Element, HtmlButtonElement, HtmlTextAreaElement};
use web_sys::{wasm_bindgen::JsCast, Element, HtmlButtonElement, HtmlTextAreaElement};

#[cfg(feature = "default-form")]
mod default_form;
Expand Down Expand Up @@ -30,7 +32,8 @@ pub const FORM_SUBMIT_ID: &str = "panic_info_form_submit";

/// Information about the panic that occurred, potentially useful to report.
///
/// Why not [`PanicInfo`](std::panic::PanicInfo)? `PanicInfo` is unable to be owned, doesn't implement `Clone`, and is `!Send`, making it unable to pass to a callback.
/// Why not [`PanicInfo`](std::panic::PanicInfo)? `PanicInfo` is unable to be owned, doesn't
/// implement `Clone`, and is `!Send`, making it unable to pass to a callback.
#[derive(Debug)]
pub struct WasmPanicInfo {
/// The file that triggered the panic
Expand All @@ -55,20 +58,25 @@ impl std::fmt::Display for WasmPanicInfo {
/// # Params
/// `container_id`: The ID of the HTML element that will be unmounted in favor of the form.\
/// `form_html`: The raw HTML that will replace the container.\
/// `on_panic_callback`: A closure that is triggered on panic automatically.\
/// `submit_callback`: The closure that will run when the user hits the send report button.
///
/// # Panics
/// This will panic (ironically) if the panic occurs in a headless environment.
pub fn set_hook_with<F>(
/// This will panic (ironically) if the panic is caught in a headless environment.
pub fn set_hook_with<F1, F2>(
container_id: impl Into<String>,
form_html: impl Into<String>,
submit_callback: F,
on_panic_callback: F1,
submit_callback: F2,
) where
F: Fn(&WasmPanicInfo) + Send + Sync + 'static,
F1: Fn(&WasmPanicInfo) + Send + Sync + 'static,
F2: Fn(&WasmPanicInfo) + Send + Sync + 'static,
{
let form_html = form_html.into();
let container_id = container_id.into();
let callback = Arc::new(submit_callback);
let already_hydrated: AtomicBool = AtomicBool::new(false);
let on_panic_callback = Arc::new(on_panic_callback);
let submit_callback = Arc::new(submit_callback);

std::panic::set_hook(Box::new(move |panic_info| {
// Collect stack trace
Expand All @@ -83,8 +91,34 @@ pub fn set_hook_with<F>(
stack_trace.push_str("\n\n");
stack_trace
};
// Print error
error(console_message.clone());

if already_hydrated.swap(true, Ordering::Relaxed) {
// Error already hydrated to the form body
return;
}

let wasm_panic_info = WasmPanicInfo {
file: panic_info
.location()
.map(|pi: &std::panic::Location<'_>| pi.file())
.unwrap_or_default()
.to_owned(),
line: panic_info
.location()
.map(|pi| pi.line())
.unwrap_or_default(),
col: panic_info
.location()
.map(|pi| pi.column())
.unwrap_or_default(),
display: panic_info.to_string(),
stack: e.stack(),
};
// Trigger callback on panic.
on_panic_callback(&wasm_panic_info);

// Retrieve the parent container we will be replacing with the report form.
let window = web_sys::window().expect("global window does not exists");
let document = window.document().expect("expecting a document on window");
Expand All @@ -93,40 +127,23 @@ pub fn set_hook_with<F>(
.unwrap_or_else(|| {
panic!("`web_panic_report`: element `{container_id}` does not exist in the DOM",)
});

// Replace inner html with our report form
parent.set_inner_html(&form_html);
// Replace the stack trace

// Hydrate the stack trace
let text_area: HtmlTextAreaElement = document
.get_element_by_id(FORM_TEXTAREA_ID)
.expect("form text id doesn't exist")
.unchecked_into();
text_area.set_value(&console_message);
// TODO: Add onclick handler to button

// Add onclick handler to the submit button
let submit_button: HtmlButtonElement = document
.get_element_by_id(FORM_SUBMIT_ID)
.expect("form submit id doesn't exist")
.unchecked_into();
// Add onclick handler to the button
let wasm_panic_info = WasmPanicInfo {
file: panic_info
.location()
.map(|pi: &std::panic::Location<'_>| pi.file())
.unwrap_or_default()
.to_owned(),
line: panic_info
.location()
.map(|pi| pi.line())
.unwrap_or_default(),
col: panic_info
.location()
.map(|pi| pi.column())
.unwrap_or_default(),
display: panic_info.to_string(),
stack: e.stack(),
};
let closure: Closure<dyn Fn()> = Closure::new({
let callback = callback.clone();
let callback = submit_callback.clone();
move || {
callback(&wasm_panic_info);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[test]
fn can_set_as_hook() {
web_panic_report::set_hook_with("", "", |_| {});
web_panic_report::set_hook_with("", "", |_| {}, |_| {});
}
Loading