Island SSR: defislands render to HTML server-side with hydration markers

Islands now render their initial state as HTML on the server, like
React SSR. The client hydrates with reactive behavior on boot.

Root causes fixed:
- is_signal/signal_value now recognize Dict-based signals (from
  signals.sx) in addition to native Signal values
- Register "context" as a primitive so the CEK deref frame handler
  can read scope stacks for reactive tracking
- Load adapter-html.sx into kernel for SX-level render-to-html
  (islands use this instead of the OCaml render module)
- Component accessors (params, body, has-children?, affinity) handle
  Island values with ? suffix aliases
- Add platform primitives: make-raw-html, raw-html-content,
  empty-dict?, for-each-indexed, cek-call

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-23 14:33:04 +00:00
parent 894321db18
commit 92bfef6406
7 changed files with 58 additions and 16 deletions

View File

@@ -256,17 +256,20 @@ and render_list_to_html head args env =
let v = env_get env name in
(match v with
| Component _ -> render_component v args env
| Island i ->
(* Islands: render initial HTML server-side (like React SSR).
Log failures so we can fix them. *)
| Island _i ->
(* Islands: SSR via the SX render-to-html from adapter-html.sx.
It handles deref/signal/computed through the CEK correctly,
and renders island bodies with hydration markers. *)
(try
let c = { c_name = i.i_name; c_params = i.i_params;
c_has_children = i.i_has_children; c_body = i.i_body;
c_closure = i.i_closure; c_affinity = "client";
c_compiled = None } in
render_component (Component c) args env
let call_expr = List (Symbol name :: args) in
let quoted = List [Symbol "quote"; call_expr] in
let render_call = List [Symbol "render-to-html"; quoted; Env env] in
let result = Sx_ref.eval_expr render_call (Env env) in
(match result with
| String s | RawHTML s -> s
| _ -> value_to_string result)
with e ->
Printf.eprintf "[ssr-island] ~%s FAILED: %s\n%!" i.i_name (Printexc.to_string e);
Printf.eprintf "[ssr-island] ~%s FAILED: %s\n%s\n%!" _i.i_name (Printexc.to_string e) (Printexc.get_backtrace ());
"")
| Macro m ->
let expanded = expand_macro m args env in