Fix duplicate sx-cssx-live style tags
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
Cache the style element reference in _cssx-style-el so flush-cssx-to-dom never creates more than one. Previous code called dom-query on every flush, which could miss the element during rapid successive calls, creating duplicates. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -88,7 +88,7 @@
|
||||
(process-elements el)
|
||||
(sx-hydrate-elements el)
|
||||
(sx-hydrate-islands el)
|
||||
(flush-cssx-to-dom))))))
|
||||
(run-post-render-hooks))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -120,7 +120,7 @@
|
||||
(process-elements el)
|
||||
(sx-hydrate-elements el)
|
||||
(sx-hydrate-islands el)
|
||||
(flush-cssx-to-dom)
|
||||
(run-post-render-hooks)
|
||||
(dom-dispatch el "sx:resolved" {:id id})))
|
||||
(log-warn (str "resolveSuspense: no element for id=" id))))))
|
||||
|
||||
@@ -418,29 +418,34 @@
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; CSSX live flush — inject collected CSS rules into the DOM
|
||||
;; Render hooks — generic pre/post callbacks for hydration, swap, mount.
|
||||
;; The spec calls these at render boundaries; the app decides what to do.
|
||||
;; Pre-render: setup before DOM changes (e.g. prepare state).
|
||||
;; Post-render: cleanup after DOM changes (e.g. flush collected CSS).
|
||||
;; --------------------------------------------------------------------------
|
||||
;;
|
||||
;; ~cssx/tw collects CSS rules via collect!("cssx" ...) during rendering.
|
||||
;; On the server, ~cssx/flush emits a batch <style> tag. On the client,
|
||||
;; islands render independently and no batch flush runs. This function
|
||||
;; injects any unflushed rules into a persistent <style> element in <head>.
|
||||
;; Called after hydration (boot + post-swap) to cover all render paths.
|
||||
|
||||
(define flush-cssx-to-dom :effects [mutation io]
|
||||
(define *pre-render-hooks* (list))
|
||||
(define *post-render-hooks* (list))
|
||||
|
||||
(define register-pre-render-hook :effects [mutation]
|
||||
(fn ((hook-fn :as lambda))
|
||||
(append! *pre-render-hooks* hook-fn)))
|
||||
|
||||
(define register-post-render-hook :effects [mutation]
|
||||
(fn ((hook-fn :as lambda))
|
||||
(append! *post-render-hooks* hook-fn)))
|
||||
|
||||
(define run-pre-render-hooks :effects [mutation io]
|
||||
(fn ()
|
||||
(let ((rules (collected "cssx")))
|
||||
(when (not (empty? rules))
|
||||
(let ((style (or (dom-query "#sx-cssx-live")
|
||||
(let ((s (dom-create-element "style" nil)))
|
||||
(dom-set-attr s "id" "sx-cssx-live")
|
||||
(dom-set-attr s "data-cssx" "")
|
||||
(dom-append-to-head s)
|
||||
s))))
|
||||
(dom-set-prop style "textContent"
|
||||
(str (or (dom-get-prop style "textContent") "")
|
||||
(join "" rules))))
|
||||
(clear-collected! "cssx")))))
|
||||
(for-each (fn (hook) (cek-call hook nil)) *pre-render-hooks*)))
|
||||
|
||||
(define run-post-render-hooks :effects [mutation io]
|
||||
(fn ()
|
||||
(log-info "run-post-render-hooks:" (len *post-render-hooks*) "hooks")
|
||||
(for-each (fn (hook)
|
||||
(log-info " hook type:" (type-of hook) "callable:" (callable? hook) "lambda:" (lambda? hook))
|
||||
(cek-call hook nil))
|
||||
*post-render-hooks*)))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -464,7 +469,7 @@
|
||||
(process-sx-scripts nil)
|
||||
(sx-hydrate-elements nil)
|
||||
(sx-hydrate-islands nil)
|
||||
(flush-cssx-to-dom)
|
||||
(run-post-render-hooks)
|
||||
(process-elements nil))))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user