Implement deref-as-shift: ReactiveResetFrame, DerefFrame, continuation capture
frames.sx: ReactiveResetFrame + DerefFrame constructors, kont-capture-to-reactive-reset, has-reactive-reset-frame?. cek.sx: deref as CEK special form, step-sf-deref pushes DerefFrame, reactive-shift-deref captures continuation as signal subscriber, ReactiveResetFrame in step-continue calls update-fn on re-render. adapter-dom.sx: cek-reactive-text/cek-reactive-attr using cek-run with ReactiveResetFrame for implicit DOM bindings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1107,6 +1107,48 @@
|
||||
(reset! sig (dom-get-prop el "value"))))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; CEK-based reactive rendering (opt-in, deref-as-shift)
|
||||
;; --------------------------------------------------------------------------
|
||||
;;
|
||||
;; When enabled, (deref sig) inside a reactive-reset boundary performs
|
||||
;; continuation capture: "the rest of this expression" becomes the subscriber.
|
||||
;; No explicit effect() wrapping needed for text/attr bindings.
|
||||
|
||||
(define *use-cek-reactive* true)
|
||||
(define enable-cek-reactive! (fn () (set! *use-cek-reactive* true)))
|
||||
|
||||
;; cek-reactive-text — create a text node bound via continuation capture
|
||||
(define cek-reactive-text :effects [render mutation]
|
||||
(fn (expr env)
|
||||
(let ((node (create-text-node ""))
|
||||
(update-fn (fn (val)
|
||||
(dom-set-text-content node (str val)))))
|
||||
(let ((initial (cek-run
|
||||
(make-cek-state expr env
|
||||
(list (make-reactive-reset-frame env update-fn true))))))
|
||||
(dom-set-text-content node (str initial))
|
||||
node))))
|
||||
|
||||
;; cek-reactive-attr — bind an attribute via continuation capture
|
||||
(define cek-reactive-attr :effects [render mutation]
|
||||
(fn (el attr-name expr env)
|
||||
(let ((update-fn (fn (val)
|
||||
(cond
|
||||
(or (nil? val) (= val false)) (dom-remove-attr el attr-name)
|
||||
(= val true) (dom-set-attr el attr-name "")
|
||||
:else (dom-set-attr el attr-name (str val))))))
|
||||
;; Mark for morph protection
|
||||
(let ((existing (or (dom-get-attr el "data-sx-reactive-attrs") ""))
|
||||
(updated (if (empty? existing) attr-name (str existing "," attr-name))))
|
||||
(dom-set-attr el "data-sx-reactive-attrs" updated))
|
||||
;; Initial render via CEK with ReactiveResetFrame
|
||||
(let ((initial (cek-run
|
||||
(make-cek-state expr env
|
||||
(list (make-reactive-reset-frame env update-fn true))))))
|
||||
(invoke update-fn initial)))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; render-dom-portal — render children into a remote target element
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user