Stepper cookie persistence: SSR + client-side save/restore
- Parse Cookie header in OCaml HTTP server for get-cookie primitive - Stepper saves step-idx to cookie via host-set! FFI on click - Stepper restores from cookie: get-cookie on server, host-get FFI on client - Cache key includes stepper cookie value to avoid stale SSR - registerNative: also update Sx_primitives table for CALL_PRIM dispatch Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1761,6 +1761,9 @@ let http_inject_shell_statics env static_dir sx_sxc =
|
||||
let templates_dir = project_dir ^ "/shared/sx/templates" in
|
||||
let client_libs = [
|
||||
templates_dir ^ "/cssx.sx";
|
||||
templates_dir ^ "/tw-layout.sx";
|
||||
templates_dir ^ "/tw-type.sx";
|
||||
templates_dir ^ "/tw.sx";
|
||||
] in
|
||||
List.iter (fun path ->
|
||||
if Sys.file_exists path then begin
|
||||
@@ -2593,6 +2596,21 @@ let http_mode port =
|
||||
_req_headers := parse_http_headers data;
|
||||
_req_body := (if method_ = "POST" || method_ = "PUT" || method_ = "PATCH"
|
||||
then extract_body data else "");
|
||||
(* Parse Cookie header into request_cookies for get-cookie primitive *)
|
||||
Hashtbl.clear _request_cookies;
|
||||
(match List.assoc_opt "cookie"
|
||||
(List.map (fun (k,v) -> (String.lowercase_ascii k, v)) !_req_headers) with
|
||||
| Some cookie_str ->
|
||||
List.iter (fun pair ->
|
||||
let trimmed = String.trim pair in
|
||||
(match String.index_opt trimmed '=' with
|
||||
| Some i ->
|
||||
let k = String.sub trimmed 0 i in
|
||||
let v = String.sub trimmed (i+1) (String.length trimmed - i - 1) in
|
||||
Hashtbl.replace _request_cookies k v
|
||||
| None -> ())
|
||||
) (String.split_on_char ';' cookie_str)
|
||||
| None -> ());
|
||||
if path = "/" then begin
|
||||
write_response fd (http_redirect "/sx/"); true
|
||||
end else
|
||||
@@ -2736,7 +2754,10 @@ let http_mode port =
|
||||
in
|
||||
write_response fd response; true
|
||||
end else if is_sx then begin
|
||||
let cache_key = if is_ajax then "ajax:" ^ path else path in
|
||||
let has_stepper_cookie = Hashtbl.mem _request_cookies "sx-home-stepper" in
|
||||
let cache_key = if is_ajax then "ajax:" ^ path
|
||||
else if has_stepper_cookie then path ^ ":step=" ^ (try Hashtbl.find _request_cookies "sx-home-stepper" with Not_found -> "")
|
||||
else path in
|
||||
match Hashtbl.find_opt response_cache cache_key with
|
||||
| Some cached -> write_response fd cached; true
|
||||
| None ->
|
||||
|
||||
@@ -401,6 +401,7 @@ let api_register_native name_js callback_js =
|
||||
js_to_value (Js.Unsafe.fun_call callback_js [| Js.Unsafe.inject (Js.array js_args) |])
|
||||
in
|
||||
let v = NativeFn (name, native_fn) in
|
||||
Sx_primitives.register name native_fn;
|
||||
ignore (env_bind global_env name v);
|
||||
Hashtbl.replace _vm_globals name v;
|
||||
Js.Unsafe.inject Js.null
|
||||
|
||||
Reference in New Issue
Block a user