My aggregated monorepo of OCaml code, automaintained
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix CodeMirror RangeError and map forward-reference in notebook

editor.ml: Clamp widget decoration positions to doc_len-1 to avoid
CodeMirror RangeError when mapping decorations through changesets.
Also catch exceptions in refresh_messages to prevent cascade failures
in cell execution. The root cause is a discrepancy between the cached
document length and CodeMirror's actual document — needs further
investigation.

interactive_map.mld: Fix forward reference to `map` in on_click
callback. Use a ref cell (map_ref) to break the self-referential
binding, since `let map = Leaflet_map.create ~on_click:(... map ...)`
is an unbound-value error in OCaml.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+21 -6
+5 -1
site/notebooks/interactive_map.mld
··· 74 74 75 75 let () = Widget.display ~id:"status" ~handlers:[] (status_view "Draw a rectangle on the map.") 76 76 77 + let map_ref : Leaflet_map.t option ref = ref None 78 + let map_get () = match !map_ref with Some m -> m | None -> failwith "map not ready" 79 + 77 80 let map = Leaflet_map.create 78 81 ~center:(52.2, 0.12) ~zoom:13 ~height:"500px" 79 82 ~on_bbox_drawn:(fun b -> ··· 91 94 training_points := (pt.lat, pt.lng, cls) :: !training_points; 92 95 let color = class_colors.(cls mod Array.length class_colors) in 93 96 let label = (!class_names).(cls) in 94 - Leaflet_map.add_marker map pt ~color ~label (); 97 + Leaflet_map.add_marker (map_get ()) pt ~color ~label (); 95 98 Widget.update ~id:"status" 96 99 (status_view (Printf.sprintf "Added %s point at %.4f, %.4f (%d points total)" 97 100 label pt.lat pt.lng (List.length !training_points)))) 98 101 () 102 + let () = map_ref := Some map 99 103 100 104 let () = Leaflet_map.enable_bbox_draw map 101 105 ]}
+16 -5
x-ocaml/src/editor.ml
··· 27 27 range ~from:at ~to_:at 28 28 @@ widget ~block:true ~side:99 29 29 @@ Widget.make (fun () -> msg)) 30 - @@ List.filter (fun (at, _) -> at <= String.length doc) 30 + @@ List.filter (fun (at, _) -> at >= 0) 31 31 @@ List.map (fun (at, msg) -> 32 + let at = min at (String.length doc) in 32 33 let at = find_line_ends at doc in 34 + (* Clamp to last character — decorations at doc.length can cause 35 + RangeError when CodeMirror maps them through changesets *) 36 + let at = min at (max 0 (String.length doc - 1)) in 33 37 (at, msg)) 34 38 @@ List.concat 35 39 @@ List.map (fun (loc, lst) -> List.map (fun m -> (loc, m)) lst) 36 40 @@ List.sort (fun (a, _) (b, _) -> Int.compare a b) cm.messages 37 41 in 38 - F.of_ it (Range_set.of' ranges) 42 + try F.of_ it (Range_set.of' ranges) 43 + with _ -> F.of_ it (Range_set.of' [||]) 39 44 40 45 let refresh_messages ed = 41 - Code_mirror.Editor.View.dispatch ed.view 42 - (Code_mirror.Compartment.reconfigure ed.messages_comp 43 - [ render_messages ed ]) 46 + try 47 + Code_mirror.Editor.View.dispatch ed.view 48 + (Code_mirror.Compartment.reconfigure ed.messages_comp 49 + [ render_messages ed ]) 50 + with _ -> () 51 + (* RangeError can occur when CodeMirror maps decoration positions 52 + through changesets if the cached doc length differs from the 53 + actual CodeMirror document length. Swallow to prevent cascade 54 + failures in the cell execution chain. *) 44 55 45 56 let custom_ln editor = 46 57 Code_mirror.Editor.View.line_numbers (fun x ->