Fix 30 test failures: OCaml renderer primitives + condition signal rename
OCaml HTML renderer (sx_render.ml) silently returned "" when env_get failed for primitive function calls (str, +, len, etc.) inside HTML elements. The Eval_error catch now falls through to eval_expr which resolves primitives correctly. Fixes 21 rendering tests. Rename condition system special form from "signal" to "signal-condition" in evaluator.sx, matching the OCaml bootstrapped evaluator (sx_ref.ml). This avoids clashing with the reactive signal function. Fixes 9 condition system tests. 1166 passed, 0 failed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -280,7 +280,10 @@ and render_list_to_html head args env =
|
||||
| _ ->
|
||||
let result = Sx_ref.eval_expr (List (head :: args)) (Env env) in
|
||||
do_render_to_html result env)
|
||||
with Eval_error _ -> "")
|
||||
with Eval_error _ ->
|
||||
(* Symbol not in env — might be a primitive; eval the full expression *)
|
||||
let result = Sx_ref.eval_expr (List (head :: args)) (Env env) in
|
||||
do_render_to_html result env)
|
||||
| _ ->
|
||||
let result = Sx_ref.eval_expr (List (head :: args)) (Env env) in
|
||||
do_render_to_html result env
|
||||
@@ -530,10 +533,13 @@ and render_list_buf buf head args env =
|
||||
| _ ->
|
||||
let result = Sx_ref.eval_expr (List (head :: args)) (Env env) in
|
||||
render_to_buf buf result env)
|
||||
with Eval_error msg ->
|
||||
(* Unknown symbol/component — skip silently during SSR.
|
||||
The client will render from page-sx. *)
|
||||
Printf.eprintf "[ssr-skip] %s\n%!" msg)
|
||||
with Eval_error _ ->
|
||||
(* Symbol not in env — might be a primitive; eval the full expression *)
|
||||
(try
|
||||
let result = Sx_ref.eval_expr (List (head :: args)) (Env env) in
|
||||
render_to_buf buf result env
|
||||
with Eval_error msg ->
|
||||
Printf.eprintf "[ssr-skip] %s\n%!" msg))
|
||||
| _ ->
|
||||
(try
|
||||
let result = Sx_ref.eval_expr (List (head :: args)) (Env env) in
|
||||
|
||||
@@ -1050,7 +1050,7 @@
|
||||
("emitted" (step-sf-emitted args env kont))
|
||||
("handler-bind" (step-sf-handler-bind args env kont))
|
||||
("restart-case" (step-sf-restart-case args env kont))
|
||||
("signal" (step-sf-signal args env kont))
|
||||
("signal-condition" (step-sf-signal args env kont))
|
||||
("invoke-restart" (step-sf-invoke-restart args env kont))
|
||||
("match" (step-sf-match args env kont))
|
||||
("dynamic-wind"
|
||||
|
||||
109
spec/tests/test-conditions.sx
Normal file
109
spec/tests/test-conditions.sx
Normal file
@@ -0,0 +1,109 @@
|
||||
(defsuite
|
||||
"handler-bind-basic"
|
||||
(deftest
|
||||
"handler-bind returns body value when no signal"
|
||||
(assert-equal
|
||||
42
|
||||
(handler-bind (((fn (c) true) (fn (c) "handled"))) 42)))
|
||||
(deftest
|
||||
"signal with matching handler returns handler value"
|
||||
(assert-equal
|
||||
"handled: boom"
|
||||
(handler-bind
|
||||
(((fn (c) true) (fn (c) (str "handled: " c))))
|
||||
(signal-condition "boom"))))
|
||||
(deftest
|
||||
"signal without handler errors"
|
||||
(assert-throws (fn () (signal-condition "unhandled"))))
|
||||
(deftest
|
||||
"signal returns handler value to call site"
|
||||
(assert-equal
|
||||
51
|
||||
(handler-bind
|
||||
(((fn (c) true) (fn (c) (* c 10))))
|
||||
(+ 1 (signal-condition 5)))))
|
||||
(deftest
|
||||
"handler-bind multiple handlers picks first match"
|
||||
(assert-equal
|
||||
"got-b"
|
||||
(handler-bind
|
||||
(((fn (c) (= c "type-a")) (fn (c) "got-a"))
|
||||
((fn (c) (= c "type-b")) (fn (c) "got-b")))
|
||||
(signal-condition "type-b"))))
|
||||
(deftest
|
||||
"nested handler-bind inner takes precedence"
|
||||
(assert-equal
|
||||
"inner-handler"
|
||||
(handler-bind
|
||||
(((fn (c) true) (fn (c) "outer")))
|
||||
(handler-bind
|
||||
(((fn (c) (= c "inner")) (fn (c) "inner-handler")))
|
||||
(signal-condition "inner")))))
|
||||
(deftest
|
||||
"handler-bind with multi-expression body"
|
||||
(assert-equal
|
||||
10
|
||||
(handler-bind (((fn (c) true) (fn (c) c))) (+ 1 2) (* 2 5)))))
|
||||
|
||||
(defsuite
|
||||
"restart-case-basic"
|
||||
(deftest
|
||||
"restart-case returns body value when no signal"
|
||||
(assert-equal 3 (restart-case (+ 1 2) (use-default () 0))))
|
||||
(deftest
|
||||
"invoke-restart finds and runs restart"
|
||||
(assert-equal
|
||||
42
|
||||
(handler-bind
|
||||
(((fn (c) true) (fn (c) (invoke-restart (quote use-default)))))
|
||||
(restart-case
|
||||
(do (signal-condition "bad") "unreachable")
|
||||
(use-default () 42)))))
|
||||
(deftest
|
||||
"invoke-restart with argument"
|
||||
(assert-equal
|
||||
99
|
||||
(handler-bind
|
||||
(((fn (c) true) (fn (c) (invoke-restart (quote use-value) 99))))
|
||||
(restart-case
|
||||
(do (signal-condition "bad") "unreachable")
|
||||
(use-value (v) v)))))
|
||||
(deftest
|
||||
"invoke-restart unknown name errors"
|
||||
(assert-throws (fn () (invoke-restart (quote nonexistent)))))
|
||||
(deftest
|
||||
"nested restart-case uses inner restart"
|
||||
(assert-equal
|
||||
"inner-fallback"
|
||||
(handler-bind
|
||||
(((fn (c) true) (fn (c) (invoke-restart (quote fallback)))))
|
||||
(restart-case
|
||||
(restart-case
|
||||
(do (signal-condition "err") "unreachable")
|
||||
(fallback () "inner-fallback"))
|
||||
(fallback () "outer-fallback")))))
|
||||
(deftest
|
||||
"signal + restart computes replacement value"
|
||||
(assert-equal
|
||||
25
|
||||
(handler-bind
|
||||
(((fn (c) true) (fn (c) (invoke-restart (quote use-value) (* c 3)))))
|
||||
(+ 10 (restart-case (signal-condition 5) (use-value (v) v)))))))
|
||||
|
||||
(defsuite
|
||||
"comp-trace"
|
||||
(deftest
|
||||
"component call creates trace frame"
|
||||
(defcomp ~trace-inner () "inner")
|
||||
(assert-equal "inner" (~trace-inner)))
|
||||
(deftest
|
||||
"nested component calls work"
|
||||
(defcomp ~trace-child () "child")
|
||||
(defcomp ~trace-parent () (~trace-child))
|
||||
(assert-equal "child" (~trace-parent)))
|
||||
(deftest
|
||||
"component error via cek-try"
|
||||
(defcomp ~broken-comp () (error "deliberate"))
|
||||
(let
|
||||
((result (cek-try (fn () (~broken-comp)))))
|
||||
(assert-true (= (type-of result) "list")))))
|
||||
Reference in New Issue
Block a user