@@ -18,7 +18,7 @@ use std::marker::PhantomData;
18
18
use std:: pin:: Pin ;
19
19
#[ cfg( not( target_arch = "wasm32" ) ) ]
20
20
use std:: sync:: Arc ;
21
- use std:: { collections:: HashMap , rc:: Rc } ;
21
+ use std:: { collections:: HashMap , panic :: PanicInfo , rc:: Rc } ;
22
22
use sycamore:: prelude:: Scope ;
23
23
use sycamore:: utils:: hydrate:: with_no_hydration_context;
24
24
use sycamore:: {
@@ -104,7 +104,6 @@ where
104
104
/// The options for constructing a Perseus app. This `struct` will tie
105
105
/// together all your code, declaring to Perseus where your templates,
106
106
/// error pages, static content, etc. are.
107
- #[ derive( Debug ) ]
108
107
pub struct PerseusAppBase < G : Html , M : MutableStore , T : TranslationsManager > {
109
108
/// The HTML ID of the root `<div>` element into which Perseus will be
110
109
/// injected.
@@ -154,6 +153,10 @@ pub struct PerseusAppBase<G: Html, M: MutableStore, T: TranslationsManager> {
154
153
/// here will only be used if it exists.
155
154
#[ cfg( not( target_arch = "wasm32" ) ) ]
156
155
static_dir : String ,
156
+ /// A handler for panics on the client-side. This could create an arbitrary
157
+ /// message for the user, or do anything else.
158
+ #[ cfg( target_arch = "wasm32" ) ]
159
+ panic_handler : Option < Box < dyn Fn ( & PanicInfo ) + Send + Sync + ' static > > ,
157
160
// We need this on the client-side to account for the unused type parameters
158
161
#[ cfg( target_arch = "wasm32" ) ]
159
162
_marker : PhantomData < ( M , T ) > ,
@@ -307,6 +310,8 @@ impl<G: Html, M: MutableStore, T: TranslationsManager> PerseusAppBase<G, M, T> {
307
310
#[ cfg( not( target_arch = "wasm32" ) ) ]
308
311
static_dir : "./static" . to_string ( ) ,
309
312
#[ cfg( target_arch = "wasm32" ) ]
313
+ panic_handler : None ,
314
+ #[ cfg( target_arch = "wasm32" ) ]
310
315
_marker : PhantomData ,
311
316
}
312
317
}
@@ -335,6 +340,7 @@ impl<G: Html, M: MutableStore, T: TranslationsManager> PerseusAppBase<G, M, T> {
335
340
plugins : Rc :: new ( Plugins :: new ( ) ) ,
336
341
// Many users won't need anything fancy in the index view, so we provide a default
337
342
index_view : DFLT_INDEX_VIEW . to_string ( ) ,
343
+ panic_handler : None ,
338
344
_marker : PhantomData ,
339
345
}
340
346
}
@@ -562,6 +568,29 @@ impl<G: Html, M: MutableStore, T: TranslationsManager> PerseusAppBase<G, M, T> {
562
568
self . pss_max_size = val;
563
569
self
564
570
}
571
+ /// Sets the browser-side panic handler for your app. This is a function
572
+ /// that will be executed if your app panics (which should never be caused
573
+ /// by Perseus unless something is seriously wrong, it's much more likely
574
+ /// to come from your code, or third-party code). If this happens, your page
575
+ /// would become totally uninteractive, with no warning to the user, since
576
+ /// Wasm will simply abort. In such cases, it is strongly recommended to
577
+ /// generate a warning message that notifies the user.
578
+ ///
579
+ /// Note that there is no access within this function to Sycamore, page
580
+ /// state, global state, or translators. Assume that your code has
581
+ /// completely imploded when you write this function.
582
+ ///
583
+ /// This has no default value.
584
+ #[ allow( unused_variables) ]
585
+ #[ allow( unused_mut) ]
586
+ pub fn panic_handler ( mut self , val : impl Fn ( & PanicInfo ) + Send + Sync + ' static ) -> Self {
587
+ #[ cfg( target_arch = "wasm32" ) ]
588
+ {
589
+ self . panic_handler = Some ( Box :: new ( val) ) ;
590
+ }
591
+ self
592
+ }
593
+
565
594
// Getters
566
595
/// Gets the HTML ID of the `<div>` at which to insert Perseus.
567
596
pub fn get_root ( & self ) -> String {
@@ -873,6 +902,14 @@ impl<G: Html, M: MutableStore, T: TranslationsManager> PerseusAppBase<G, M, T> {
873
902
874
903
scoped_static_aliases
875
904
}
905
+ /// Takes the user-set panic handler out and returns it as an owned value,
906
+ /// allowing it to be used as an actual panic hook.
907
+ #[ cfg( target_arch = "wasm32" ) ]
908
+ pub fn take_panic_handler (
909
+ & mut self ,
910
+ ) -> Option < Box < dyn Fn ( & PanicInfo ) + Send + Sync + ' static > > {
911
+ self . panic_handler . take ( )
912
+ }
876
913
}
877
914
878
915
/// The component that represents the entrypoint at which Perseus will inject
0 commit comments