sx-http: CSSX source before components in defs, JIT closure bug identified
Move client library sources (cssx.sx) before defcomp/defisland definitions in component-defs so defines are evaluated first. Identified root cause of CSSX "Not callable: nil" errors: JIT compiler captures free variable values at compile time instead of looking them up at runtime from vm_globals. When ~cssx/tw's JIT code calls cssx-process-token, it uses the compile-time snapshot (nil) instead of the runtime value (lambda). The function IS in global_env (type-of returns "lambda") but the JIT bytecode doesn't see it. Fix needed: JIT compiler should emit GLOBAL_GET instructions for free variables that reference vm_globals at runtime, not capture at compile. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1653,8 +1653,24 @@ let read_css_file path =
|
||||
|
||||
(** Pre-compute shell statics and inject into env as __shell-* vars. *)
|
||||
let http_inject_shell_statics env static_dir sx_sxc =
|
||||
(* Component definitions for client *)
|
||||
(* Component definitions for client.
|
||||
Client library sources FIRST (CSSX etc.) so defines are available
|
||||
before defcomp/defisland bodies that reference them. *)
|
||||
let buf = Buffer.create 65536 in
|
||||
let project_dir = try Sys.getenv "SX_PROJECT_DIR" with Not_found ->
|
||||
Filename.dirname (Filename.dirname static_dir) in
|
||||
let templates_dir = project_dir ^ "/shared/sx/templates" in
|
||||
let client_libs = [
|
||||
templates_dir ^ "/cssx.sx";
|
||||
] in
|
||||
List.iter (fun path ->
|
||||
if Sys.file_exists path then begin
|
||||
let src = In_channel.with_open_text path In_channel.input_all in
|
||||
Buffer.add_string buf src;
|
||||
Buffer.add_char buf '\n'
|
||||
end
|
||||
) client_libs;
|
||||
(* Then component/island definitions *)
|
||||
Hashtbl.iter (fun _sym v ->
|
||||
match v with
|
||||
| Component c ->
|
||||
@@ -1671,22 +1687,6 @@ let http_inject_shell_statics env static_dir sx_sxc =
|
||||
i.i_name ps (serialize_value i.i_body))
|
||||
| _ -> ()
|
||||
) env.bindings;
|
||||
(* Prepend client library source files — these define functions that
|
||||
island components need at runtime (CSSX, signals, etc.).
|
||||
Read directly from .sx files, same as Quart's _CLIENT_LIBRARY_SOURCES. *)
|
||||
let project_dir = try Sys.getenv "SX_PROJECT_DIR" with Not_found ->
|
||||
Filename.dirname (Filename.dirname static_dir) in
|
||||
let templates_dir = project_dir ^ "/shared/sx/templates" in
|
||||
let client_libs = [
|
||||
templates_dir ^ "/cssx.sx";
|
||||
] in
|
||||
List.iter (fun path ->
|
||||
if Sys.file_exists path then begin
|
||||
let src = In_channel.with_open_text path In_channel.input_all in
|
||||
Buffer.add_string buf src;
|
||||
Buffer.add_char buf '\n'
|
||||
end
|
||||
) client_libs;
|
||||
let raw_defs = Buffer.contents buf in
|
||||
(* Component-defs are inlined in <script type="text/sx">.
|
||||
The escape_sx_string function handles </ → <\\/ inside string
|
||||
|
||||
Reference in New Issue
Block a user