A fork of mtelver's day10 project
at main2 196 lines 5.7 kB view raw view rendered
1# js_top_worker Demo 2 3This directory contains a comprehensive demo showcasing all features of js_top_worker - an OCaml toplevel that runs in a browser WebWorker. 4 5## Features Demonstrated 6 7- **Basic Execution**: Run OCaml code and see results 8- **Multiple Environments**: Create isolated execution contexts 9- **MIME Output**: Rich output (HTML, SVG, images) via `Mime_printer` 10- **Autocomplete**: Code completion suggestions 11- **Type Information**: Hover-style type queries 12- **Error Reporting**: Static analysis and error detection 13- **Directives**: `#show`, `#install_printer`, `#help`, etc. 14- **Custom Printers**: Install custom value formatters 15- **Library Loading**: Dynamic `#require` for findlib packages 16- **Toplevel Scripts**: Execute multi-phrase scripts 17 18## Prerequisites 19 20You need: 21- OCaml 5.2+ with opam 22- The following opam packages installed: 23 - js_of_ocaml, js_of_ocaml-ppx 24 - dune (3.0+) 25 - All js_top_worker dependencies 26 27## Quick Start 28 29### 1. Build the Project 30 31From the repository root: 32 33```bash 34# Install dependencies (if not already done) 35opam install . --deps-only 36 37# Build everything 38dune build 39``` 40 41### 2. Prepare the Example Directory 42 43The build generates the `_opam` directory with compiled libraries: 44 45```bash 46# This is done automatically by dune, but you can also run manually: 47dune build @example/default 48``` 49 50This creates `_build/default/example/_opam/` containing: 51- `worker.js` - The WebWorker toplevel 52- `lib/` - Compiled CMI files and JavaScript-compiled CMA files 53- `findlib_index.json` - Index of available packages 54 55### 3. Start the Web Server 56 57```bash 58cd _build/default/example 59python3 server.py 8000 60``` 61 62Or use any HTTP server with CORS support. The `server.py` script adds necessary headers. 63 64### 4. Open the Demo 65 66Navigate to: **http://localhost:8000/demo.html** 67 68## File Structure 69 70``` 71example/ 72├── demo.html # Main demo page (feature showcase) 73├── demo.js # JavaScript client for the demo 74├── worker.ml # WebWorker entry point (1 line!) 75├── server.py # Development server with CORS 76├── dune # Build configuration 77├── _opam/ # Generated: compiled packages 78│ ├── worker.js # The compiled WebWorker 79│ ├── lib/ # CMI files and .cma.js files 80│ └── findlib_index.json # Package index 81└── *.html, *.ml # Other example files 82``` 83 84## Adding More Libraries 85 86To add additional OCaml libraries to the demo, edit the `dune` file: 87 88```dune 89(rule 90 (targets 91 (dir _opam)) 92 (action 93 (run jtw opam -o _opam str stringext core YOUR_LIBRARY))) 94``` 95 96Then rebuild: 97 98```bash 99dune build @example/default 100``` 101 102The `jtw opam` command: 1031. Finds all transitive dependencies 1042. Copies CMI files for type information 1053. Compiles CMA files to JavaScript with `js_of_ocaml` 1064. Generates the findlib index and dynamic_cmis.json files 107 108## How It Works 109 110### Architecture 111 112``` 113┌─────────────────┐ postMessage/JSON-RPC ┌─────────────────┐ 114│ Browser Tab │ ◄──────────────────────────► │ WebWorker │ 115│ (demo.js) │ │ (worker.js) │ 116│ │ │ │ 117│ - UI rendering │ │ - OCaml toplevel│ 118│ - RPC client │ │ - Merlin engine │ 119│ - MIME display │ │ - #require │ 120└─────────────────┘ └─────────────────┘ 121``` 122 123### RPC Methods 124 125| Method | Description | 126|--------|-------------| 127| `init` | Initialize toplevel with config | 128| `setup` | Setup an environment (start toplevel) | 129| `exec` | Execute a phrase | 130| `exec_toplevel` | Execute a toplevel script | 131| `create_env` | Create isolated environment | 132| `destroy_env` | Destroy an environment | 133| `list_envs` | List all environments | 134| `complete_prefix` | Get autocomplete suggestions | 135| `type_enclosing` | Get type at position | 136| `query_errors` | Get errors/warnings for code | 137 138### MIME Output 139 140User code can produce rich output using the `Mime_printer` module: 141 142```ocaml 143(* SVG output *) 144Mime_printer.push "image/svg" "<svg>...</svg>";; 145 146(* HTML output *) 147Mime_printer.push "text/html" "<table>...</table>";; 148 149(* Base64-encoded image *) 150Mime_printer.push ~encoding:Base64 "image/png" "iVBORw0KGgo...";; 151``` 152 153The demo page renders these appropriately in the UI. 154 155## Troubleshooting 156 157### "Worker error" on startup 158 159- Check browser console for details 160- Ensure `_opam/worker.js` exists 161- Verify the server is running with CORS headers 162 163### "Failed to fetch" errors 164 165- The worker loads files via HTTP; check network tab 166- Ensure `lib/ocaml/` directory has CMI files 167- Check `findlib_index.json` file exists 168 169### Library not found with #require 170 171- Add the library to the `jtw opam` command in dune 172- Rebuild with `dune build @example/default` 173- Check `_opam/lib/PACKAGE/META` exists 174 175### Autocomplete/type info not working 176 177- Merlin needs CMI files; ensure they're in `_opam/lib/` 178- The `dynamic_cmis.json` file must be present for each library 179 180## Development 181 182To modify the worker libraries: 183 1841. Edit files in `lib/` (core implementation) 1852. Edit files in `lib-web/` (browser-specific code) 1863. Rebuild: `dune build` 1874. Refresh the browser (worker is cached, may need hard refresh) 188 189The worker entry point is minimal: 190 191```ocaml 192(* worker.ml *) 193let _ = Js_top_worker_web.Worker.run () 194``` 195 196All the complexity is in the `js_top_worker-web` library.