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

@@ -32,6 +32,8 @@
"raw-html" (raw-html-content expr)
;; Spread — emit attrs to nearest element provider
"spread" (do (emit! "element-attrs" (spread-attrs expr)) "")
;; Thunk — unwrap and render the inner expression (from letrec TCO)
"thunk" (render-to-html (thunk-expr expr) (thunk-env expr))
;; Everything else — evaluate first
:else (render-value-to-html (trampoline (eval-expr expr env)) env))))
@@ -45,6 +47,7 @@
"list" (render-list-to-html val env)
"raw-html" (raw-html-content val)
"spread" (do (emit! "element-attrs" (spread-attrs val)) "")
"thunk" (render-to-html (thunk-expr val) (thunk-env val))
:else (escape-html (str val)))))