11open Util ;
22
3+ type current_exception =
4+ | Update (string )
5+ | Calculate (string );
6+
7+ let last_exception : ref (option (exn )) = ref (None );
8+ let current_exception : ref (option (current_exception )) = ref (None );
9+
10+ let set_last_exception = exn => {
11+ last_exception := Some (exn);
12+ };
13+
14+ let clear_last_exception = () => {
15+ last_exception := None ;
16+ };
17+
18+ let set_current_exception = exn_type => {
19+ current_exception := Some (exn_type);
20+ };
21+
22+ let clear_current_exception = () => {
23+ current_exception := None ;
24+ };
25+
326module Model = {
427 [@ deriving (sexp, yojson)]
528 type state = Logged . Model . t ;
6- [@ deriving (sexp, yojson)]
7- type current_exception =
8- | NoException
9- | Update (string )
10- | Calculate (string );
1129
1230 [@ deriving (sexp, yojson)]
13- type t = {
14- model: state ,
15- current_exception,
16- };
31+ type t = {model: state };
1732
1833 let equal = (=== );
1934
20- let load = () => {
21- model: Logged . Model . load() ,
22- current_exception: NoException ,
23- };
35+ let load = () => {model: Logged . Model . load() };
2436};
2537
2638module Update = {
@@ -38,12 +50,15 @@ module Update = {
3850 : Updated . t(Model . t) =>
3951 switch (action) {
4052 | Globals (ClearException ) =>
41- {
42- ... model,
43- current_exception: NoException ,
53+ clear_last_exception() ;
54+ clear_current_exception() ;
55+ model |> Updated . return_quiet;
56+ | Globals (RethrowException ) =>
57+ switch (last_exception^ ) {
58+ | None => model |> Updated . return_quiet
59+ | Some (exn ) => raise (exn)
4460 }
45- |> Updated . return_quiet
46- | _ when model. current_exception == NoException =>
61+ | _ when current_exception^ == None =>
4762 try ({
4863 let updated =
4964 Logged . Update . update(
@@ -57,7 +72,6 @@ module Update = {
5772 ... updated,
5873 model: {
5974 model: updated. model,
60- current_exception: NoException ,
6175 },
6276 };
6377 }) {
@@ -71,12 +85,11 @@ module Update = {
7185 print_endline("cannot perform action" );
7286 model |> Updated . return_quiet;
7387 | exn =>
88+ set_last_exception(exn);
7489 let msg = Printexc . to_string(exn);
7590 print_endline("CrashHandling: Caught exception in update: " ++ msg);
76- Updated . return_quiet({
77- ... model,
78- current_exception: Update (msg),
79- });
91+ set_current_exception(Update (msg));
92+ model |> Updated . return_quiet;
8093 }
8194 | _ => model |> Updated . return_quiet
8295 };
@@ -94,15 +107,13 @@ module Update = {
94107 model:
95108 model. model
96109 |> Logged . Update . calculate(~schedule_action, ~is_edited, ~dynamics),
97- current_exception: model. current_exception,
98110 }) {
99111 | exn =>
112+ set_last_exception(exn);
100113 let msg = Printexc . to_string(exn);
101114 print_endline("CrashHandling: Caught exception in calculate: " ++ msg);
102- {
103- ... previous_model,
104- current_exception: Calculate (msg),
105- };
115+ set_current_exception(Calculate (msg));
116+ previous_model;
106117 };
107118};
108119
@@ -111,7 +122,12 @@ module View = {
111122 open WebUtil . Node ;
112123
113124 let hsod_view =
114- (~title: string , ~msg: string , ~inject_backtrack: Ui_effect . t (unit )) =>
125+ (
126+ ~title: string ,
127+ ~msg: string ,
128+ ~inject_backtrack: Ui_effect . t (unit ),
129+ ~inject_rethrow: Ui_effect . t (unit ),
130+ ) =>
115131 div(
116132 ~attrs= [ Attr . class_("hsod-container" )] ,
117133 [
@@ -181,6 +197,14 @@ module View = {
181197 ] ,
182198 [ Node . text("Revert to previous state" )] ,
183199 ),
200+ button(
201+ ~attrs= [
202+ Attr . create("type" , "button" ),
203+ Attr . class_("hsod-button" ),
204+ Attr . on_click(_ => inject_rethrow),
205+ ] ,
206+ [ Node . text("Rethrow exception" )] ,
207+ ),
184208 ] ,
185209 ),
186210 ] ,
@@ -194,26 +218,33 @@ module View = {
194218
195219 let view =
196220 (~get_log_and, ~inject: Update . t => Ui_effect . t (unit ), model: Model . t ) =>
197- switch (model. current_exception) {
198- | NoException => Logged . View . view(~get_log_and, ~inject, model. model)
199- | Update (msg ) =>
221+ switch (current_exception^ ) {
222+ | None =>
223+ try (Logged . View . view(~get_log_and, ~inject, model. model)) {
224+ | exn =>
225+ set_last_exception(exn);
226+ let msg = Printexc . to_string(exn);
227+ set_current_exception(Update (msg));
228+ hsod_view(
229+ ~title= "Exception during View" ,
230+ ~msg,
231+ ~inject_backtrack= inject(Globals (Undo )),
232+ ~inject_rethrow= inject(Globals (RethrowException )),
233+ );
234+ }
235+ | Some (Update (msg )) =>
200236 hsod_view(
201237 ~title= "Exception during Update" ,
202238 ~msg,
203239 ~inject_backtrack= inject(Globals (ClearException )),
240+ ~inject_rethrow= inject(Globals (RethrowException )),
204241 )
205- | Calculate (msg ) =>
242+ | Some ( Calculate (msg ) ) =>
206243 hsod_view(
207244 ~title= "Exception during Calculate" ,
208245 ~msg,
209246 ~inject_backtrack= inject(Globals (ClearException )),
247+ ~inject_rethrow= inject(Globals (RethrowException )),
210248 )
211- | exception exn =>
212- let msg = Printexc . to_string(exn);
213- hsod_view(
214- ~title= "Exception during View" ,
215- ~msg,
216- ~inject_backtrack= inject(Globals (Undo )),
217- );
218249 };
219250};
0 commit comments