···3344let current_attribute attr = Brr.El.at (Jstr.of_string attr) current_script
5566-let extra_load =
77- match current_attribute "src-load" with
88- | None -> None
99- | Some url -> Some (Jstr.to_string url)
1010-116let read_meta name =
127 let doc = Brr.Document.to_jv Brr.G.document in
138 let selector = Jstr.of_string ("meta[name=\"" ^ name ^ "\"]") in
···1813 if Jv.is_none content then None
1914 else Some (Jv.to_string content)
20152121-let backend_name =
2222- match current_attribute "backend" with
2323- | Some name -> Jstr.to_string name
2424- | None ->
2525- match read_meta "x-ocaml-backend" with
2626- | Some name -> name
2727- | None -> "builtin"
1616+let () =
1717+ let extra_load =
1818+ match current_attribute "src-load" with
1919+ | None -> None
2020+ | Some url -> Some (Jstr.to_string url)
2121+ in
28222929-let findlib_requires =
3030- match read_meta "x-ocaml-packages" with
3131- | None -> None
3232- | Some s ->
3333- let pkgs = List.filter (fun s -> s <> "")
3434- (List.map String.trim (String.split_on_char ',' s)) in
3535- if pkgs = [] then None else Some pkgs
2323+ let backend_name =
2424+ match current_attribute "backend" with
2525+ | Some name -> Jstr.to_string name
2626+ | None ->
2727+ match read_meta "x-ocaml-backend" with
2828+ | Some name -> name
2929+ | None -> "builtin"
3030+ in
3131+3232+ let findlib_requires =
3333+ match read_meta "x-ocaml-packages" with
3434+ | None -> None
3535+ | Some s ->
3636+ let pkgs = List.filter (fun s -> s <> "")
3737+ (List.map String.trim (String.split_on_char ',' s)) in
3838+ if pkgs = [] then None else Some pkgs
3939+ in
36403737-let resolve_url relative =
3838- let url_ctor = Jv.get Jv.global "URL" in
3939- let loc = Jv.get (Jv.get Jv.global "window") "location" in
4040- let href = Jv.to_string (Jv.get loc "href") in
4141- let url_obj = Jv.new' url_ctor [| Jv.of_string relative; Jv.of_string href |] in
4242- Jv.to_string (Jv.get url_obj "href")
4141+ let resolve_url relative =
4242+ let url_ctor = Jv.get Jv.global "URL" in
4343+ let loc = Jv.get (Jv.get Jv.global "window") "location" in
4444+ let href = Jv.to_string (Jv.get loc "href") in
4545+ let url_obj = Jv.new' url_ctor [| Jv.of_string relative; Jv.of_string href |] in
4646+ Jv.to_string (Jv.get url_obj "href")
4747+ in
43484444-let findlib_index_url =
4545- match read_meta "x-ocaml-universe" with
4646- | None -> None
4747- | Some base ->
4848- let base = if String.length base > 0 && base.[String.length base - 1] = '/'
4949- then base else base ^ "/" in
5050- Some (resolve_url (base ^ "findlib_index.json"))
4949+ let findlib_index_url =
5050+ match read_meta "x-ocaml-universe" with
5151+ | None -> None
5252+ | Some base ->
5353+ let base = if String.length base > 0 && base.[String.length base - 1] = '/'
5454+ then base else base ^ "/" in
5555+ Some (resolve_url (base ^ "findlib_index.json"))
5656+ in
51575252-(** Synchronous XHR fetch of a small text resource.
5353- Used only for the findlib_index.json pre-fetch (~200 bytes)
5454- to extract compiler info before creating the worker. *)
5555-let sync_fetch_text url =
5656- let xhr = Jv.new' (Jv.get Jv.global "XMLHttpRequest") [||] in
5757- Jv.call xhr "open" [| Jv.of_string "GET"; Jv.of_string url; Jv.of_bool false |] |> ignore;
5858- (try Jv.call xhr "send" [||] |> ignore with _ -> ());
5959- let status = Jv.to_int (Jv.get xhr "status") in
6060- if status = 200 then Some (Jv.to_string (Jv.get xhr "responseText"))
6161- else None
5858+ let sync_fetch_text url =
5959+ let xhr = Jv.new' (Jv.get Jv.global "XMLHttpRequest") [||] in
6060+ Jv.call xhr "open" [| Jv.of_string "GET"; Jv.of_string url; Jv.of_bool false |] |> ignore;
6161+ (try Jv.call xhr "send" [||] |> ignore with _ -> ());
6262+ let status = Jv.to_int (Jv.get xhr "status") in
6363+ if status = 200 then Some (Jv.to_string (Jv.get xhr "responseText"))
6464+ else None
6565+ in
62666363-(** Parse the compiler object from findlib_index.json.
6464- Uses browser JSON.parse — no OCaml JSON library needed. *)
6565-let findlib_index_json =
6666- match findlib_index_url with
6767- | None -> None
6868- | Some url ->
6969- match sync_fetch_text url with
6767+ let findlib_index_json =
6868+ match findlib_index_url with
7069 | None -> None
7171- | Some text ->
7272- (try
7373- Some (Jv.call (Jv.get Jv.global "JSON") "parse" [| Jv.of_string text |])
7474- with _ -> None)
7070+ | Some url ->
7171+ match sync_fetch_text url with
7272+ | None -> None
7373+ | Some text ->
7474+ (try
7575+ Some (Jv.call (Jv.get Jv.global "JSON") "parse" [| Jv.of_string text |])
7676+ with _ -> None)
7777+ in
75787676-let findlib_index_base_dir =
7777- match findlib_index_url with
7878- | None -> ""
7979- | Some fi_url ->
8080- match String.rindex_opt fi_url '/' with
8181- | Some i -> String.sub fi_url 0 (i + 1)
8282- | None -> fi_url
7979+ let findlib_index_base_dir =
8080+ match findlib_index_url with
8181+ | None -> ""
8282+ | Some fi_url ->
8383+ match String.rindex_opt fi_url '/' with
8484+ | Some i -> String.sub fi_url 0 (i + 1)
8585+ | None -> fi_url
8686+ in
83878484-(** Derive the worker URL from findlib_index.json's compiler field.
8585- Supports two modes:
8686- - Direct: compiler.worker_url (relative to findlib_index.json)
8787- - Day10-style: compiler.version + compiler.content_hash constructs
8888- ../../../compiler/{version}/{content_hash}/worker.js *)
8989-let worker_url_from_findlib_index =
9090- match findlib_index_json with
9191- | None -> None
9292- | Some json ->
9393- let compiler = Jv.get json "compiler" in
9494- if Jv.is_none compiler || Jv.is_undefined compiler then None
9595- else
9696- let worker_url = Jv.get compiler "worker_url" in
9797- if not (Jv.is_none worker_url || Jv.is_undefined worker_url) then
9898- Some (findlib_index_base_dir ^ Jv.to_string worker_url)
8888+ let worker_url_from_findlib_index =
8989+ match findlib_index_json with
9090+ | None -> None
9191+ | Some json ->
9292+ let compiler = Jv.get json "compiler" in
9393+ if Jv.is_none compiler || Jv.is_undefined compiler then None
9994 else
100100- try
101101- let version = Jv.to_string (Jv.get compiler "version") in
102102- let content_hash = Jv.to_string (Jv.get compiler "content_hash") in
103103- Some (findlib_index_base_dir ^ "../../../compiler/" ^ version ^ "/" ^ content_hash ^ "/worker.js")
104104- with _ -> None
9595+ let worker_url = Jv.get compiler "worker_url" in
9696+ if not (Jv.is_none worker_url || Jv.is_undefined worker_url) then
9797+ Some (findlib_index_base_dir ^ Jv.to_string worker_url)
9898+ else
9999+ try
100100+ let version = Jv.to_string (Jv.get compiler "version") in
101101+ let content_hash = Jv.to_string (Jv.get compiler "content_hash") in
102102+ Some (findlib_index_base_dir ^ "../../../compiler/" ^ version ^ "/" ^ content_hash ^ "/worker.js")
103103+ with _ -> None
104104+ in
105105106106-let worker_url =
107107- (* Priority: 1) explicit x-ocaml-worker meta tag,
108108- 2) compiler field from findlib_index.json,
109109- 3) src-worker script attribute *)
110110- match read_meta "x-ocaml-worker" with
111111- | Some url -> url
112112- | None ->
113113- match worker_url_from_findlib_index with
114114- | Some url -> url
106106+ let worker_url =
107107+ match read_meta "x-ocaml-worker" with
108108+ | Some url -> Some url
115109 | None ->
116116- match current_attribute "src-worker" with
110110+ match worker_url_from_findlib_index with
111111+ | Some url -> Some url
117112 | None ->
118118- if backend_name = "builtin" then
119119- failwith "x-ocaml script missing src-worker attribute"
120120- else ""
121121- | Some url -> Jstr.to_string url
113113+ match current_attribute "src-worker" with
114114+ | None ->
115115+ if backend_name = "builtin" then None
116116+ else Some ""
117117+ | Some url -> Some (Jstr.to_string url)
118118+ in
122119123123-let backend = Backend.make ~backend:backend_name ?extra_load ?findlib_requires
124124- ?findlib_index:findlib_index_url worker_url
120120+ match worker_url with
121121+ | None ->
122122+ (* No worker URL available — x-ocaml elements on this page are inert
123123+ (e.g. code blocks on non-interactive pages due to resource leak). *)
124124+ ()
125125+ | Some worker_url ->
125126126126-let format_config =
127127- match current_attribute "x-ocamlformat" with
128128- | None -> None
129129- | Some conf -> Some (Jstr.to_string conf)
127127+ let backend = Backend.make ~backend:backend_name ?extra_load ?findlib_requires
128128+ ?findlib_index:findlib_index_url worker_url
129129+ in
130130131131-let extra_style = current_attribute "src-style"
132132-let inline_style = current_attribute "inline-style"
131131+ let format_config =
132132+ match current_attribute "x-ocamlformat" with
133133+ | None -> None
134134+ | Some conf -> Some (Jstr.to_string conf)
135135+ in
133136134134-let default_run_on =
135135- current_attribute "run-on" |> Option.map Jstr.to_string
137137+ let extra_style = current_attribute "src-style" in
138138+ let inline_style = current_attribute "inline-style" in
139139+140140+ let default_run_on =
141141+ current_attribute "run-on" |> Option.map Jstr.to_string
142142+ in
136143137137-let page =
138138- Page.create ~backend ?extra_style ?inline_style ?default_run_on
139139- ?format_config ()
144144+ let page =
145145+ Page.create ~backend ?extra_style ?inline_style ?default_run_on
146146+ ?format_config ()
147147+ in
140148141141-let elt_name =
142142- match current_attribute "elt-name" with
143143- | None -> Jstr.of_string "x-ocaml"
144144- | Some name -> name
149149+ let elt_name =
150150+ match current_attribute "elt-name" with
151151+ | None -> Jstr.of_string "x-ocaml"
152152+ | Some name -> name
153153+ in
145154146146-let _ =
147147- Webcomponent.define elt_name @@ fun this ->
155155+ ignore @@ Webcomponent.define elt_name @@ fun this ->
148156 let _cell = Page.register page this in
149157 ()