Files
rose-ash/shared/static/wasm/sx/harness-reactive.sx
giles 8d3ab040ef Fix WASM browser: broken links (&rest bytecode) + broken reactive counter (ListRef mutation)
Two bugs fixed:

1. Links: bytecode compiler doesn't handle &rest params — treats them as
   positional, so (first rest) gets a raw string instead of a list.
   Replaced &rest with explicit optional params in all bytecode-compiled
   web SX files (dom-query, dom-add-listener, browser-push-state, etc.).
   The VM already pads missing args with Nil.

2. Reactive counter: signal-remove-sub! used (filter ...) which returns
   immutable List, but signal-add-sub! uses (append!) which only mutates
   ListRef. Subscribers silently vanished after first effect re-run.
   Fixed by adding remove! primitive that mutates ListRef in-place.

Also:
- Added evalVM API to WASM kernel (compile + run through bytecode VM)
- Added scope tracing (scope-push!/pop!/peek/context instrumentation)
- Added Playwright reactive mode for debugging island signal/DOM state
- Replaced cek-call with direct calls in core-signals.sx effect/computed
- Recompiled all 23 bytecode modules

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 14:08:49 +00:00

111 lines
2.5 KiB
Plaintext

(define
assert-signal-value
:effects ()
(fn
((sig :as any) expected)
(let
((actual (deref sig)))
(assert=
actual
expected
(str "Expected signal value " expected ", got " actual)))))
(define
assert-signal-has-subscribers
:effects ()
(fn
((sig :as any))
(assert
(> (len (signal-subscribers sig)) 0)
"Expected signal to have subscribers")))
(define
assert-signal-no-subscribers
:effects ()
(fn
((sig :as any))
(assert
(= (len (signal-subscribers sig)) 0)
"Expected signal to have no subscribers")))
(define
assert-signal-subscriber-count
:effects ()
(fn
((sig :as any) (n :as number))
(let
((actual (len (signal-subscribers sig))))
(assert= actual n (str "Expected " n " subscribers, got " actual)))))
(define
simulate-signal-set!
:effects (mutation)
(fn ((sig :as any) value) (reset! sig value)))
(define
simulate-signal-swap!
:effects (mutation)
(fn ((sig :as any) (f :as lambda)) (swap! sig f)))
(define
assert-computed-dep-count
:effects ()
(fn
((sig :as any) (n :as number))
(let
((actual (len (signal-deps sig))))
(assert= actual n (str "Expected " n " deps, got " actual)))))
(define
assert-computed-depends-on
:effects ()
(fn
((computed-sig :as any) (dep-sig :as any))
(assert
(contains? (signal-deps computed-sig) dep-sig)
"Expected computed to depend on the given signal")))
(define
count-effect-runs
:effects (mutation)
(fn
((thunk :as lambda))
(let
((count (signal 0)))
(effect (fn () (deref count)))
(let
((run-count 0)
(tracker
(effect
(fn () (set! run-count (+ run-count 1)) (cek-call thunk nil)))))
run-count))))
(define
make-test-signal
:effects (mutation)
(fn
(initial-value)
(let
((sig (signal initial-value)) (history (list)))
(effect (fn () (append! history (deref sig))))
{:signal sig :history history})))
(define
assert-batch-coalesces
:effects (mutation)
(fn
((thunk :as lambda) (expected-notify-count :as number))
(let
((notify-count 0) (sig (signal 0)))
(effect (fn () (deref sig) (set! notify-count (+ notify-count 1))))
(set! notify-count 0)
(batch thunk)
(assert=
notify-count
expected-notify-count
(str
"Expected "
expected-notify-count
" notifications, got "
notify-count)))))