Fix isomorphic SSR: revert inline opcodes, add named let compilation, fix cookie decode
Three bugs broke island SSR rendering of the home stepper widget: 1. Inline VM opcodes (OP_ADD..OP_DEC) broke JIT-compiled functions. The compiler emitted single-byte opcodes for first/rest/len/= etc. that produced wrong results in complex recursive code (sx-parse returned nil, split-tag produced 1 step instead of 16). Reverted compiler to use CALL_PRIM for all primitives. VM opcode handlers kept for future use. 2. Named let (let loop ((x init)) body) had no compiler support — silently produced broken bytecode. Added desugaring to letrec. 3. URL-encoded cookie values not decoded server-side. Client set-cookie uses encodeURIComponent but Werkzeug doesn't decode cookie values. Added unquote() in bridge cookie injection. Also: call-lambda used eval_expr which copies Dict values (signals), breaking mutations through aser lambda calls. Switched to cek_call. Also: stepper preview now includes ~cssx/tw spreads for SSR styling. Tests: 1317 JS, 1114 OCaml, 26 integration (2 pre-existing failures) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -292,11 +292,15 @@ let setup_io_env env =
|
||||
| _ -> raise (Eval_error "ctx: expected 1 arg"));
|
||||
|
||||
bind "call-lambda" (fun args ->
|
||||
(* Use cek_call instead of eval_expr to avoid re-evaluating
|
||||
already-evaluated args. eval_expr copies Dict values (signals)
|
||||
during evaluation, so mutations in the lambda body would affect
|
||||
the copy, not the original. *)
|
||||
match args with
|
||||
| [fn_val; List call_args; Env e] ->
|
||||
Sx_ref.eval_expr (List (fn_val :: call_args)) (Env e)
|
||||
| [fn_val; List call_args; Env _e] ->
|
||||
Sx_ref.cek_call fn_val (List call_args)
|
||||
| [fn_val; List call_args] ->
|
||||
Sx_ref.eval_expr (List (fn_val :: call_args)) (Env env)
|
||||
Sx_ref.cek_call fn_val (List call_args)
|
||||
| _ -> raise (Eval_error "call-lambda: expected (fn args env?)"));
|
||||
|
||||
(* Register HO forms as callable NativeFn — the CEK machine handles them
|
||||
@@ -377,11 +381,15 @@ let setup_evaluator_bridge env =
|
||||
in resolve v
|
||||
| _ -> raise (Eval_error "trampoline: expected 1 arg"));
|
||||
bind "call-lambda" (fun args ->
|
||||
(* Use cek_call instead of eval_expr to avoid re-evaluating
|
||||
already-evaluated args. eval_expr copies Dict values (signals)
|
||||
during evaluation, so mutations in the lambda body would affect
|
||||
the copy, not the original. *)
|
||||
match args with
|
||||
| [fn_val; List call_args; Env e] ->
|
||||
Sx_ref.eval_expr (List (fn_val :: call_args)) (Env e)
|
||||
| [fn_val; List call_args; Env _e] ->
|
||||
Sx_ref.cek_call fn_val (List call_args)
|
||||
| [fn_val; List call_args] ->
|
||||
Sx_ref.eval_expr (List (fn_val :: call_args)) (Env env)
|
||||
Sx_ref.cek_call fn_val (List call_args)
|
||||
| _ -> raise (Eval_error "call-lambda: expected (fn args env?)"));
|
||||
bind "cek-call" (fun args ->
|
||||
match args with
|
||||
|
||||
Reference in New Issue
Block a user