Fix CSSX styling: trampoline wiring + scope-emit!/emitted for adapter-html.sx
Root causes of missing CSSX classes in SSR: 1. _sx_trampoline_fn in sx_primitives.ml was never wired — call_any in HO forms (map/filter/for-each) returned unresolved Thunks, so callbacks like render-lambda-html's param binding never executed. Fixed in bootstrap.py FIXUPS: wire Sx_primitives._sx_trampoline_fn after eval_expr. 2. adapter-html.sx used (emit! ...) and (emitted ...) which are CEK special forms (walk kont for ScopeAccFrame), but scope-push!/scope-pop! use the hashtable. CEK frames and hashtable are two different scope systems. Fixed: adapter uses scope-emit!/scope-emitted (hashtable primitives). 3. env-* operations (env-has?, env-get, env-bind!, env-set!, env-extend, env-merge) only accepted Env type. adapter-html.sx passes Dict as env. Fixed: all env ops go through unwrap_env which handles Dict/Nil. Also: fix merge conflict in sx/sx/geography/index.sx, remove duplicate scope primitives from sx_primitives.ml (sx_server.ml registers them). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -194,6 +194,43 @@ let () = Sx_primitives.register "clear-collected!" (fun args ->
|
||||
Nil
|
||||
| _ -> Nil)
|
||||
|
||||
(* emit!/emitted — adapter-html.sx uses these for spread attr collection *)
|
||||
let () = Sx_primitives.register "scope-emit!" (fun args ->
|
||||
match args with
|
||||
| [String name; value] ->
|
||||
let stack = try Hashtbl.find _scope_stacks name with Not_found -> [] in
|
||||
(match stack with
|
||||
| List items :: rest ->
|
||||
Hashtbl.replace _scope_stacks name (List (items @ [value]) :: rest)
|
||||
| v :: rest ->
|
||||
(* Non-list top — wrap current entries as list + new value *)
|
||||
Hashtbl.replace _scope_stacks name (List [value] :: v :: rest)
|
||||
| [] ->
|
||||
Hashtbl.replace _scope_stacks name [List [value]]);
|
||||
Nil
|
||||
| _ -> Nil)
|
||||
|
||||
let () = Sx_primitives.register "emitted" (fun args ->
|
||||
match args with
|
||||
| [String name] ->
|
||||
let stack = try Hashtbl.find _scope_stacks name with Not_found -> [] in
|
||||
(match stack with List items :: _ -> List items | _ -> List [])
|
||||
| _ -> List [])
|
||||
|
||||
let () = Sx_primitives.register "scope-emitted" (fun args ->
|
||||
match args with
|
||||
| [String name] ->
|
||||
let stack = try Hashtbl.find _scope_stacks name with Not_found -> [] in
|
||||
(match stack with List items :: _ -> List items | _ -> List [])
|
||||
| _ -> List [])
|
||||
|
||||
let () = Sx_primitives.register "provide-push!" (fun args ->
|
||||
match Sx_primitives.get_primitive "scope-push!" with
|
||||
| NativeFn (_, fn) -> fn args | _ -> Nil)
|
||||
let () = Sx_primitives.register "provide-pop!" (fun args ->
|
||||
match Sx_primitives.get_primitive "scope-pop!" with
|
||||
| NativeFn (_, fn) -> fn args | _ -> Nil)
|
||||
|
||||
let () = Sx_primitives.register "scope-emit!" (fun args ->
|
||||
match args with
|
||||
| [String name; value] ->
|
||||
@@ -510,7 +547,7 @@ let make_server_env () =
|
||||
Route to the OCaml CEK machine. *)
|
||||
bind "eval-expr" (fun args ->
|
||||
match args with
|
||||
| [expr; Env e] -> Sx_ref.eval_expr expr (Env e)
|
||||
| [expr; e] -> Sx_ref.eval_expr expr (Env (Sx_runtime.unwrap_env e))
|
||||
| [expr] -> Sx_ref.eval_expr expr (Env env)
|
||||
| _ -> raise (Eval_error "eval-expr: expected (expr env?)"));
|
||||
bind "trampoline" (fun args ->
|
||||
@@ -792,34 +829,35 @@ let make_server_env () =
|
||||
| [v] -> String (inspect v)
|
||||
| _ -> raise (Eval_error "sx-serialize: expected 1 arg"));
|
||||
|
||||
(* Env operations *)
|
||||
(* Env operations — accept both Env and Dict (adapter-html.sx passes dicts) *)
|
||||
let uw = Sx_runtime.unwrap_env in
|
||||
bind "env-get" (fun args ->
|
||||
match args with
|
||||
| [Env e; String k] -> env_get e k
|
||||
| [Env e; Keyword k] -> env_get e k
|
||||
| [e; String k] -> Sx_types.env_get (uw e) k
|
||||
| [e; Keyword k] -> Sx_types.env_get (uw e) k
|
||||
| _ -> raise (Eval_error "env-get: expected env and string"));
|
||||
|
||||
bind "env-has?" (fun args ->
|
||||
match args with
|
||||
| [Env e; String k] -> Bool (env_has e k)
|
||||
| [Env e; Keyword k] -> Bool (env_has e k)
|
||||
| [e; String k] -> Bool (Sx_types.env_has (uw e) k)
|
||||
| [e; Keyword k] -> Bool (Sx_types.env_has (uw e) k)
|
||||
| _ -> raise (Eval_error "env-has?: expected env and string"));
|
||||
|
||||
bind "env-bind!" (fun args ->
|
||||
match args with
|
||||
| [Env e; String k; v] -> env_bind e k v
|
||||
| [Env e; Keyword k; v] -> env_bind e k v
|
||||
| [e; String k; v] -> Sx_types.env_bind (uw e) k v
|
||||
| [e; Keyword k; v] -> Sx_types.env_bind (uw e) k v
|
||||
| _ -> raise (Eval_error "env-bind!: expected env, key, value"));
|
||||
|
||||
bind "env-set!" (fun args ->
|
||||
match args with
|
||||
| [Env e; String k; v] -> env_set e k v
|
||||
| [Env e; Keyword k; v] -> env_set e k v
|
||||
| [e; String k; v] -> Sx_types.env_set (uw e) k v
|
||||
| [e; Keyword k; v] -> Sx_types.env_set (uw e) k v
|
||||
| _ -> raise (Eval_error "env-set!: expected env, key, value"));
|
||||
|
||||
bind "env-extend" (fun args ->
|
||||
match args with
|
||||
| [Env e] -> Env (env_extend e)
|
||||
| [e] -> Env (Sx_types.env_extend (uw e))
|
||||
| _ -> raise (Eval_error "env-extend: expected env"));
|
||||
|
||||
bind "env-merge" (fun args ->
|
||||
|
||||
Reference in New Issue
Block a user