AJAX on main thread, fix double-push in click delegation

- AJAX requests (SX-Request: true) now render on main thread instead
  of queueing behind slow full-page renders in worker pool
- Remove pushState from click handler — handle-history does it after
  swap succeeds, preventing double-push that triggered popstate handler

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 18:06:22 +00:00
parent 80931e4972
commit 5b55b75a9a
2 changed files with 25 additions and 10 deletions

View File

@@ -2238,12 +2238,29 @@ let http_mode port =
match Hashtbl.find_opt response_cache cache_key with
| Some cached -> write_response fd cached; true
| None ->
let headers = if is_ajax then parse_http_headers data else [] in
Mutex.lock render_mutex;
render_queue := !render_queue @ [(fd, path, headers)];
Condition.signal render_cond;
Mutex.unlock render_mutex;
false
if is_ajax then begin
(* AJAX: render on main thread — aser only, fast, no SSR.
Avoids queueing behind slow full-page renders. *)
let headers = parse_http_headers data in
let response =
try match http_render_page env path headers with
| Some body ->
let resp = http_response ~content_type:"text/sx; charset=utf-8" body in
Hashtbl.replace response_cache cache_key resp; resp
| None -> http_response ~status:404 "nil"
with e ->
Printf.eprintf "[ajax] Error for %s: %s\n%!" path (Printexc.to_string e);
http_response ~status:500 "nil"
in
write_response fd response; true
end else begin
(* Full page: queue to render worker *)
Mutex.lock render_mutex;
render_queue := !render_queue @ [(fd, path, [])];
Condition.signal render_cond;
Mutex.unlock render_mutex;
false
end
end else if String.length path > 8 && String.sub path 0 8 = "/static/" then begin
write_response fd (serve_static_file static_dir path); true
end else begin

View File

@@ -464,10 +464,8 @@
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
e.preventDefault();
var url = el.getAttribute("href") || el.getAttribute("sx-get");
// Push URL first (execute-request doesn't handle URL updates)
if (el.getAttribute("sx-push-url")) {
history.pushState({}, "", url);
}
// Don't push URL here — execute-request's handle-history does it.
// Double-push causes popstate handler to clobber the SX swap.
// Store the element reference for SX to pick up
window.__sxClickEl = el;
try {