|
1 | | -= How to debug an OCaml program compiled to JavaScript. |
| 1 | += Debugging |
| 2 | + |
| 3 | +This page explains how to debug OCaml programs compiled to JavaScript. |
| 4 | + |
| 5 | +== Compiler flags |
2 | 6 |
|
3 | | -== Use the right compiler flags |
4 | 7 | === OCaml flags |
5 | | -Make sure to use {{{-g}}} flags when compiling and linking OCaml bytecode. |
6 | | -Js_of_ocaml will attempt to preserve variable names. |
| 8 | + |
| 9 | +Use {{{-g}}} when compiling and linking OCaml bytecode. Js_of_ocaml will |
| 10 | +attempt to preserve variable names. |
7 | 11 |
|
8 | 12 | === Js_of_ocaml flags |
9 | | - * {{{--pretty}}} - format the generated JavaScript in a readable way and try to keep OCaml variable names. |
10 | | - * {{{--no-inline}}} - prevent function inlining. |
11 | | - * {{{--debug-info}}} - annotate the JavaScript file with locations from the OCaml sources. |
12 | | - * {{{--source-map}}} - enable source-map support |
13 | 13 |
|
14 | | -== JavaScript stacktrace |
| 14 | +|= Flag |= Description | |
| 15 | +| {{{--pretty}}} | Format JavaScript readably, preserve OCaml variable names | |
| 16 | +| {{{--no-inline}}} | Prevent function inlining | |
| 17 | +| {{{--debug-info}}} | Add source location comments | |
| 18 | +| {{{--source-map}}} | Generate source map | |
| 19 | + |
| 20 | +=== Dune configuration |
| 21 | + |
| 22 | +For development builds, add to your dune file: |
| 23 | + |
| 24 | +{{{ |
| 25 | +(executable |
| 26 | + (name main) |
| 27 | + (modes js) |
| 28 | + (js_of_ocaml (flags --pretty --source-map))) |
| 29 | +}}} |
| 30 | + |
| 31 | +== Source maps |
| 32 | + |
| 33 | +Source maps map generated JavaScript back to OCaml sources. With source maps |
| 34 | +enabled, you can set breakpoints, step through code, and inspect variables |
| 35 | +directly in your OCaml files. |
| 36 | + |
| 37 | +To enable source maps: |
15 | 38 |
|
16 | | -See <<a_manual chapter="errors"|Error handling>> for details on attaching |
17 | | -JavaScript stack traces to OCaml exceptions using {{{OCAMLRUNPARAM=b=1}}} or |
18 | | -the {{{--enable with-js-error}}} compiler flag. |
| 39 | +{{{ |
| 40 | +js_of_ocaml --source-map program.byte |
| 41 | +}}} |
| 42 | + |
| 43 | +This generates {{{program.js}}} and {{{program.js.map}}}. |
19 | 44 |
|
20 | 45 | == Breakpoints |
21 | 46 |
|
22 | | -Set breakpoints using browser developer tools (see https://developer.chrome.com/docs/devtools/javascript). |
23 | | -Alternatively, set breakpoints programmatically by calling {{{Js.debugger ()}}}. Note that |
24 | | -browsers only stop at breakpoints when developer tools are open. |
| 47 | +=== In browser developer tools |
| 48 | + |
| 49 | +Open browser developer tools (F12), navigate to the Sources panel, and set |
| 50 | +breakpoints in your OCaml files (when using source maps) or JavaScript files. |
| 51 | + |
| 52 | +See https://developer.chrome.com/docs/devtools/javascript for details. |
| 53 | + |
| 54 | +=== Programmatic breakpoints |
| 55 | + |
| 56 | +Insert breakpoints in your OCaml code: |
| 57 | + |
| 58 | +<<code language="ocaml"| |
| 59 | +let my_function x = |
| 60 | + Js_of_ocaml.Js.debugger (); (* Breaks here when devtools are open *) |
| 61 | + x + 1 |
| 62 | +>> |
| 63 | + |
| 64 | +Note: Browsers only pause at {{{debugger}}} statements when developer tools are open. |
| 65 | + |
| 66 | +== Debugging in Node.js |
| 67 | + |
| 68 | +=== Using --inspect |
| 69 | + |
| 70 | +Run your program with Node.js inspector: |
| 71 | + |
| 72 | +{{{ |
| 73 | +node --inspect _build/default/main.bc.js |
| 74 | +}}} |
| 75 | + |
| 76 | +This prints a URL like: |
| 77 | + |
| 78 | +{{{ |
| 79 | +Debugger listening on ws://127.0.0.1:9229/... |
| 80 | +}}} |
| 81 | + |
| 82 | +=== Chrome DevTools for Node.js |
| 83 | + |
| 84 | +1. Run {{{node --inspect}}} or {{{node --inspect-brk}}} (breaks on first line) |
| 85 | +2. Open Chrome and navigate to {{{chrome://inspect}}} |
| 86 | +3. Click "Open dedicated DevTools for Node" |
| 87 | +4. Your program appears in the Sources panel |
| 88 | + |
| 89 | +== Stack traces |
| 90 | + |
| 91 | +=== Attaching JavaScript backtraces |
| 92 | + |
| 93 | +To get JavaScript stack traces attached to OCaml exceptions: |
| 94 | + |
| 95 | +{{{ |
| 96 | +OCAMLRUNPARAM=b=1 node program.js |
| 97 | +}}} |
| 98 | + |
| 99 | +Or compile with: |
| 100 | + |
| 101 | +{{{ |
| 102 | +js_of_ocaml --enable with-js-error program.byte |
| 103 | +}}} |
| 104 | + |
| 105 | +See <<a_manual chapter="errors"|Error handling>> for details. |
| 106 | + |
| 107 | +== Chrome DevTools tips |
| 108 | + |
| 109 | +Useful settings in Chrome DevTools (Settings > Experiments): |
| 110 | + |
| 111 | +* **Display variable values inline while debugging** - Shows values next to variables |
| 112 | +* **Resolve variable names** - Maps minified names back to original names |
25 | 113 |
|
26 | | -== Source map |
27 | | -Source map is used to map the generated JavaScript code to original sources. |
28 | | -After compiling with sourcemap enabled, using developers tools, one can set breakpoints, |
29 | | -step through the code, and inspect variables directly in OCaml sources. |
| 114 | +== See also |
30 | 115 |
|
31 | | -== About Chrome DevTools |
32 | | -Useful settings for Chrome DevTools: |
33 | | -* Display variable values inline while debugging |
34 | | -* Resolve variable names (hidden DevTools Experiments, see https://developer.chrome.com/docs/devtools/settings/experiments) |
| 116 | +* <<a_manual chapter="errors"|Error handling>> - Exception handling between OCaml and JavaScript |
| 117 | +* <<a_manual chapter="options"|Command line options>> - Full list of compiler flags |
0 commit comments