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:
@@ -83,3 +83,35 @@
|
||||
(test "= with booleans" (= (= true true) true))
|
||||
(test "= with keywords" (= (= :foo :foo) true))
|
||||
(test "not with list" (= (not (list 1)) false))
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Recursive mutation — VM closure capture must preserve mutable state
|
||||
;; --------------------------------------------------------------------------
|
||||
;;
|
||||
;; Regression: recursive functions that append! to a shared mutable list
|
||||
;; lost mutations after the first call under JIT. The VM closure capture
|
||||
;; was copying the list value instead of sharing the mutable reference.
|
||||
|
||||
(test "recursive append! to shared list"
|
||||
(let ((walk (fn (items result)
|
||||
(when (not (empty? items))
|
||||
(append! result (first items))
|
||||
(walk (rest items) result)))))
|
||||
(let ((result (list)))
|
||||
(walk (list "a" "b" "c") result)
|
||||
(= (len result) 3))))
|
||||
|
||||
(test "recursive tree walk with append!"
|
||||
(let ((walk (fn (expr result)
|
||||
(cond
|
||||
(not (list? expr))
|
||||
(append! result "leaf")
|
||||
(empty? expr) nil
|
||||
:else
|
||||
(do (append! result "open")
|
||||
(for-each (fn (c) (walk c result)) (rest expr))
|
||||
(append! result "close"))))))
|
||||
(let ((tree (first (sx-parse "(div \"a\" (span \"b\") \"c\")")))
|
||||
(result (list)))
|
||||
(walk tree result)
|
||||
(= (len result) 7))))
|
||||
|
||||
Reference in New Issue
Block a user