Fix thunk handling for island SSR + effect no-op on server

- trampoline resolves Thunk values (sf-letrec returns them for TCO)
- render-to-html handles "thunk" type by unwrapping expr+env
- effect overridden to no-op after loading signals.sx (prevents
  reactive loops during SSR — effects are DOM side-effects)
- Added thunk?/thunk-expr/thunk-env primitives
- Added DOM API stubs for SSR (dom-query, schedule-idle, etc.)

Header island renders fully with styling. Stepper island still
fails SSR (letrec + complex body hits "Undefined symbol: div"
in eval path — render mode not active during CEK letrec eval).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-23 15:31:58 +00:00
parent f3c0cbd8e2
commit f4610e1799
4 changed files with 33 additions and 4 deletions

View File

@@ -413,6 +413,18 @@ let make_server_env () =
bind "dom-get-data" (fun _args -> Nil);
bind "event-detail" (fun _args -> Nil);
bind "promise-then" (fun _args -> Nil);
bind "thunk?" (fun args -> match args with [Thunk _] -> Bool true | _ -> Bool false);
bind "thunk-expr" (fun args -> match args with [v] -> thunk_expr v | _ -> Nil);
bind "thunk-env" (fun args -> match args with [v] -> thunk_env v | _ -> Nil);
bind "schedule-idle" (fun _args -> Nil);
bind "dom-query" (fun _args -> Nil);
bind "dom-query-all" (fun _args -> List []);
bind "dom-set-prop" (fun _args -> Nil);
bind "dom-get-attr" (fun _args -> Nil);
bind "dom-set-attr" (fun _args -> Nil);
bind "dom-text-content" (fun _args -> String "");
bind "dom-set-text-content" (fun _args -> Nil);
bind "dom-body" (fun _args -> Nil);
(* Raw HTML — platform primitives for adapter-html.sx *)
bind "make-raw-html" (fun args ->
@@ -503,7 +515,12 @@ let make_server_env () =
| _ -> raise (Eval_error "eval-expr: expected (expr env?)"));
bind "trampoline" (fun args ->
match args with
| [v] -> v (* CEK never produces thunks *)
| [v] ->
(* sf-letrec returns thunks — resolve them *)
let rec resolve v = match v with
| Thunk (expr, env) -> resolve (Sx_ref.eval_expr expr (Env env))
| _ -> v
in resolve v
| _ -> raise (Eval_error "trampoline: expected 1 arg"));
bind "call-lambda" (fun args ->
match args with