OCaml CEK machine compiled to WebAssembly for browser execution
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 23m17s

- wasm_of_ocaml compiles OCaml SX engine to WASM (722/722 spec tests)
- js_of_ocaml fallback also working (722/722 spec tests)
- Thin JS platform layer (sx-platform.js) with ~80 DOM/browser natives
- Lambda callback bridge: SX lambdas callable from JS via handle table
- Side-channel pattern bypasses js_of_ocaml return-value property stripping
- Web adapters (signals, deps, router, adapter-html) load as SX source
- Render mode dispatch: HTML tags + fragments route to OCaml renderer
- Island/component accessors handle both Component and Island types
- Dict-based signal support (signals.sx creates dicts, not native Signal)
- Scope stack implementation (collect!/collected/emit!/emitted/context)
- Bundle script embeds web adapters + WASM loader + platform layer
- SX_USE_WASM env var toggles WASM engine in dev/production
- Bootstrap extended: --web flag transpiles web adapters, :effects stripping

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-16 07:13:49 +00:00
parent 5ab3ecb7e0
commit 0caa965de0
44 changed files with 5167 additions and 171 deletions

View File

@@ -131,35 +131,44 @@ let render_html_element tag args env =
(List.map (fun c -> render_to_html c env) children) in
"<" ^ tag ^ attr_str ^ ">" ^ content ^ "</" ^ tag ^ ">"
let render_component_generic ~params ~has_children ~body ~closure args env =
let kwargs = Hashtbl.create 8 in
let children_exprs = ref [] in
let skip = ref false in
let len = List.length args in
List.iteri (fun idx arg ->
if !skip then skip := false
else match arg with
| Keyword k when idx + 1 < len ->
let v = Sx_ref.eval_expr (List.nth args (idx + 1)) (Env env) in
Hashtbl.replace kwargs k v;
skip := true
| _ ->
children_exprs := arg :: !children_exprs
) args;
let children = List.rev !children_exprs in
let local = env_merge closure env in
List.iter (fun p ->
let v = match Hashtbl.find_opt kwargs p with Some v -> v | None -> Nil in
ignore (env_bind local p v)
) params;
if has_children then begin
let rendered_children = String.concat ""
(List.map (fun c -> render_to_html c env) children) in
ignore (env_bind local "children" (RawHTML rendered_children))
end;
render_to_html body local
let render_component comp args env =
match comp with
| Component c ->
let kwargs = Hashtbl.create 8 in
let children_exprs = ref [] in
let skip = ref false in
let len = List.length args in
List.iteri (fun idx arg ->
if !skip then skip := false
else match arg with
| Keyword k when idx + 1 < len ->
let v = Sx_ref.eval_expr (List.nth args (idx + 1)) (Env env) in
Hashtbl.replace kwargs k v;
skip := true
| _ ->
children_exprs := arg :: !children_exprs
) args;
let children = List.rev !children_exprs in
let local = env_merge c.c_closure env in
List.iter (fun p ->
let v = match Hashtbl.find_opt kwargs p with Some v -> v | None -> Nil in
ignore (env_bind local p v)
) c.c_params;
if c.c_has_children then begin
let rendered_children = String.concat ""
(List.map (fun c -> render_to_html c env) children) in
ignore (env_bind local "children" (RawHTML rendered_children))
end;
render_to_html c.c_body local
render_component_generic
~params:c.c_params ~has_children:c.c_has_children
~body:c.c_body ~closure:c.c_closure args env
| Island i ->
render_component_generic
~params:i.i_params ~has_children:i.i_has_children
~body:i.i_body ~closure:i.i_closure args env
| _ -> ""
let expand_macro (m : macro) args _env =
@@ -249,7 +258,7 @@ and render_list_to_html head args env =
(try
let v = env_get env name in
(match v with
| Component _ -> render_component v args env
| Component _ | Island _ -> render_component v args env
| Macro m ->
let expanded = expand_macro m args env in
do_render_to_html expanded env