Fix aser list flattening bug, add wire format test suite (41 tests)
The sync aser-call in adapter-sx.sx didn't flatten list results from map/filter in positional children — serialize(list) wrapped in parens creating ((div ...) ...) which re-parses as an invalid call. Rewrote aser-call from reduce to for-each (bootstrapper can't nest for-each inside reduce lambdas) and added list flattening in both aser-call and aser-fragment. Also adds test-aser.sx (41 tests), render-sx platform function, expanded test-render.sx (+7 map/filter children tests), and specs async-eval-slot-inner in adapter-async.sx. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1149,6 +1149,64 @@
|
||||
results)))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; async-eval-slot-inner — server-side slot expansion for aser mode
|
||||
;; --------------------------------------------------------------------------
|
||||
;;
|
||||
;; Coordinates component expansion for server-rendered pages:
|
||||
;; 1. If expression is a direct component call (~name ...), expand it
|
||||
;; 2. Otherwise aser the expression, then check if result is a (~...)
|
||||
;; call that should be re-expanded
|
||||
;;
|
||||
;; Platform primitives required:
|
||||
;; (sx-parse src) — parse SX source string
|
||||
;; (make-sx-expr s) — wrap as SxExpr
|
||||
;; (sx-expr? x) — check if SxExpr
|
||||
;; (set-expand-components!) — enable component expansion context var
|
||||
|
||||
(define-async async-eval-slot-inner
|
||||
(fn (expr env ctx)
|
||||
(let ((result
|
||||
(if (and (list? expr) (not (empty? expr)))
|
||||
(let ((head (first expr)))
|
||||
(if (and (= (type-of head) "symbol")
|
||||
(starts-with? (symbol-name head) "~"))
|
||||
(let ((name (symbol-name head))
|
||||
(val (if (env-has? env name) (env-get env name) nil)))
|
||||
(if (component? val)
|
||||
(async-aser-component val (rest expr) env ctx)
|
||||
;; Islands and unknown components — fall through to aser
|
||||
(async-maybe-expand-result (async-aser expr env ctx) env ctx)))
|
||||
(async-maybe-expand-result (async-aser expr env ctx) env ctx)))
|
||||
(async-maybe-expand-result (async-aser expr env ctx) env ctx))))
|
||||
;; Normalize result to SxExpr
|
||||
(if (sx-expr? result)
|
||||
result
|
||||
(if (nil? result)
|
||||
(make-sx-expr "")
|
||||
(if (string? result)
|
||||
(make-sx-expr result)
|
||||
(make-sx-expr (serialize result))))))))
|
||||
|
||||
|
||||
(define-async async-maybe-expand-result
|
||||
(fn (result env ctx)
|
||||
;; If the aser result is a component call string like "(~foo ...)",
|
||||
;; re-parse and expand it. This handles indirect component references
|
||||
;; (e.g. a let binding that evaluates to a component call).
|
||||
(let ((raw (if (sx-expr? result)
|
||||
(trim (str result))
|
||||
(if (string? result)
|
||||
(trim result)
|
||||
nil))))
|
||||
(if (and raw (starts-with? raw "(~"))
|
||||
(let ((parsed (sx-parse raw)))
|
||||
(if (and parsed (not (empty? parsed)))
|
||||
(async-eval-slot-inner (first parsed) env ctx)
|
||||
result))
|
||||
result))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Platform interface — async adapter
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user