Replace invoke with cek-call in reactive island primitives
All signal operations (computed, effect, batch, etc.) now dispatch function calls through cek-call, which routes SX lambdas via cek-run and native callables via apply. This replaces the invoke shim. Key changes: - cek.sx: add cek-call (defined before reactive-shift-deref), replace invoke in subscriber disposal and ReactiveResetFrame handler - signals.sx: replace all 11 invoke calls with cek-call - js.sx: fix octal escape in js-quote-string (char-from-code 0) - platform_js.py: fix JS append to match Python (list concat semantics), add Continuation type guard in PLATFORM_CEK_JS, add scheduleIdle safety check, module ordering (cek before signals) - platform_py.py: fix ident-char regex (remove [ ] from valid chars), module ordering (cek before signals) - run_js_sx.py: emit PLATFORM_CEK_JS before transpiled spec files - page-functions.sx: add cek and provide page functions for SX URLs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,14 +23,11 @@
|
||||
;; (scope-pop! "sx-reactive") → void
|
||||
;; (context "sx-reactive" nil) → dict or nil
|
||||
;;
|
||||
;; Runtime callable dispatch:
|
||||
;; (invoke f &rest args) → any — call f with args; handles both
|
||||
;; native host functions AND SX lambdas
|
||||
;; from runtime-evaluated code (islands).
|
||||
;; Transpiled code emits direct calls
|
||||
;; f(args) which fail on SX lambdas.
|
||||
;; invoke goes through the evaluator's
|
||||
;; dispatch (call-fn) so either works.
|
||||
;; CEK callable dispatch:
|
||||
;; (cek-call f args) → any — call f with args list via CEK.
|
||||
;; Dispatches through cek-run for SX
|
||||
;; lambdas, apply for native callables.
|
||||
;; Defined in cek.sx.
|
||||
;;
|
||||
;; ==========================================================================
|
||||
|
||||
@@ -150,7 +147,7 @@
|
||||
;; Push scope-based tracking context for this computed
|
||||
(let ((ctx (dict "deps" (list) "notify" recompute)))
|
||||
(scope-push! "sx-reactive" ctx)
|
||||
(let ((new-val (invoke compute-fn)))
|
||||
(let ((new-val (cek-call compute-fn nil)))
|
||||
(scope-pop! "sx-reactive")
|
||||
;; Save discovered deps
|
||||
(signal-set-deps! s (get ctx "deps"))
|
||||
@@ -184,7 +181,7 @@
|
||||
(fn ()
|
||||
(when (not disposed)
|
||||
;; Run previous cleanup if any
|
||||
(when cleanup-fn (invoke cleanup-fn))
|
||||
(when cleanup-fn (cek-call cleanup-fn nil))
|
||||
|
||||
;; Unsubscribe from old deps
|
||||
(for-each
|
||||
@@ -195,7 +192,7 @@
|
||||
;; Push scope-based tracking context
|
||||
(let ((ctx (dict "deps" (list) "notify" run-effect)))
|
||||
(scope-push! "sx-reactive" ctx)
|
||||
(let ((result (invoke effect-fn)))
|
||||
(let ((result (cek-call effect-fn nil)))
|
||||
(scope-pop! "sx-reactive")
|
||||
(set! deps (get ctx "deps"))
|
||||
;; If effect returns a function, it's the cleanup
|
||||
@@ -209,7 +206,7 @@
|
||||
(let ((dispose-fn
|
||||
(fn ()
|
||||
(set! disposed true)
|
||||
(when cleanup-fn (invoke cleanup-fn))
|
||||
(when cleanup-fn (cek-call cleanup-fn nil))
|
||||
(for-each
|
||||
(fn ((dep :as signal)) (signal-remove-sub! dep run-effect))
|
||||
deps)
|
||||
@@ -232,7 +229,7 @@
|
||||
(define batch :effects [mutation]
|
||||
(fn ((thunk :as lambda))
|
||||
(set! *batch-depth* (+ *batch-depth* 1))
|
||||
(invoke thunk)
|
||||
(cek-call thunk nil)
|
||||
(set! *batch-depth* (- *batch-depth* 1))
|
||||
(when (= *batch-depth* 0)
|
||||
(let ((queue *batch-queue*))
|
||||
@@ -323,7 +320,7 @@
|
||||
(fn ((disposable :as lambda))
|
||||
(let ((collector (context "sx-island-scope" nil)))
|
||||
(when collector
|
||||
(invoke collector disposable)))))
|
||||
(cek-call collector (list disposable))))))
|
||||
|
||||
|
||||
;; ==========================================================================
|
||||
@@ -362,7 +359,7 @@
|
||||
;; Parent island scope and sibling marshes are unaffected.
|
||||
(let ((disposers (dom-get-data marsh-el "sx-marsh-disposers")))
|
||||
(when disposers
|
||||
(for-each (fn ((d :as lambda)) (invoke d)) disposers)
|
||||
(for-each (fn ((d :as lambda)) (cek-call d nil)) disposers)
|
||||
(dom-set-data marsh-el "sx-marsh-disposers" nil)))))
|
||||
|
||||
|
||||
@@ -384,7 +381,7 @@
|
||||
(let ((registry *store-registry*))
|
||||
;; Only create the store once — subsequent calls return existing
|
||||
(when (not (has-key? registry name))
|
||||
(set! *store-registry* (assoc registry name (invoke init-fn))))
|
||||
(set! *store-registry* (assoc registry name (cek-call init-fn nil))))
|
||||
(get *store-registry* name))))
|
||||
|
||||
(define use-store :effects []
|
||||
@@ -443,7 +440,7 @@
|
||||
(fn (e)
|
||||
(let ((detail (event-detail e))
|
||||
(new-val (if transform-fn
|
||||
(invoke transform-fn detail)
|
||||
(cek-call transform-fn (list detail))
|
||||
detail)))
|
||||
(reset! target-signal new-val))))))
|
||||
;; Return cleanup — removes listener on dispose/re-run
|
||||
@@ -474,7 +471,7 @@
|
||||
(fn ((fetch-fn :as lambda))
|
||||
(let ((state (signal (dict "loading" true "data" nil "error" nil))))
|
||||
;; Kick off the async operation
|
||||
(promise-then (invoke fetch-fn)
|
||||
(promise-then (cek-call fetch-fn nil)
|
||||
(fn (data) (reset! state (dict "loading" false "data" data "error" nil)))
|
||||
(fn (err) (reset! state (dict "loading" false "data" nil "error" err))))
|
||||
state)))
|
||||
|
||||
Reference in New Issue
Block a user