diff --git a/hosts/ocaml/bin/sx_server.ml b/hosts/ocaml/bin/sx_server.ml index 4c56206..4689590 100644 --- a/hosts/ocaml/bin/sx_server.ml +++ b/hosts/ocaml/bin/sx_server.ml @@ -394,6 +394,16 @@ let make_server_env () = bind "set-render-active!" (fun _args -> Nil); bind "render-active?" (fun _args -> Bool true); + (* Browser APIs — no-op stubs for SSR *) + bind "local-storage-get" (fun _args -> Nil); + bind "local-storage-set" (fun _args -> Nil); + bind "dom-listen" (fun _args -> NativeFn ("noop", fun _ -> Nil)); + bind "dom-dispatch" (fun _args -> Nil); + bind "dom-set-data" (fun _args -> Nil); + bind "dom-get-data" (fun _args -> Nil); + bind "event-detail" (fun _args -> Nil); + bind "promise-then" (fun _args -> Nil); + (* Raw HTML — platform primitives for adapter-html.sx *) bind "make-raw-html" (fun args -> match args with [String s] -> RawHTML s | [v] -> RawHTML (value_to_string v) | _ -> Nil); diff --git a/shared/sx/ocaml_bridge.py b/shared/sx/ocaml_bridge.py index dc1e8fd..45eb572 100644 --- a/shared/sx/ocaml_bridge.py +++ b/shared/sx/ocaml_bridge.py @@ -397,14 +397,18 @@ class OcamlBridge: # All directories loaded into the Python env all_dirs = list(set(_watched_dirs) | _dirs_from_cache) - # Web adapters + signals (aser lives in adapter-sx.sx, - # signals.sx provides reactive primitives for island SSR) + # Isomorphic libraries: signals, rendering, freeze scopes web_dir = os.path.join(os.path.dirname(__file__), "../../web") if os.path.isdir(web_dir): for web_file in ["signals.sx", "adapter-html.sx", "adapter-sx.sx"]: path = os.path.normpath(os.path.join(web_dir, web_file)) if os.path.isfile(path): all_files.append(path) + # Spec library files (loaded after adapters) + for spec_lib in ["freeze.sx"]: + path = os.path.normpath(os.path.join(spec_dir, spec_lib)) + if os.path.isfile(path): + all_files.append(path) for directory in sorted(all_dirs): files = sorted(