Fix island dep scanning + spread-through-reactive-if debug
deps.sx: scan island bodies for component deps (was only scanning "component" and "macro", missing "island" type). This ensures ~cssx/tw and its dependencies are sent to the client for islands. cssx.sx: move if inside make-spread arg so it's evaluated by eval-expr (no reactive wrapping) instead of render-to-dom which applies reactive-if inside island scope, converting the spread into a fragment and losing the class attrs. Added island dep tests at 3 levels: test-deps.sx (spec), test_deps.py (Python), test_parity.py (ref vs fallback). sx-browser.js: temporary debug logging at spread detection points. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -73,7 +73,7 @@
|
||||
(append! seen n)
|
||||
(let ((val (env-get env n)))
|
||||
(cond
|
||||
(= (type-of val) "component")
|
||||
(or (= (type-of val) "component") (= (type-of val) "island"))
|
||||
(for-each (fn ((ref :as string)) (transitive-deps-walk ref seen env))
|
||||
(scan-refs (component-body val)))
|
||||
(= (type-of val) "macro")
|
||||
@@ -105,7 +105,7 @@
|
||||
(for-each
|
||||
(fn ((name :as string))
|
||||
(let ((val (env-get env name)))
|
||||
(when (= (type-of val) "component")
|
||||
(when (or (= (type-of val) "component") (= (type-of val) "island"))
|
||||
(component-set-deps! val (transitive-deps name env)))))
|
||||
(env-components env))))
|
||||
|
||||
|
||||
@@ -2757,7 +2757,7 @@ def transitive_deps_walk(n, seen, env):
|
||||
if sx_truthy((not sx_truthy(contains_p(seen, n)))):
|
||||
seen.append(n)
|
||||
val = env_get(env, n)
|
||||
if sx_truthy((type_of(val) == 'component')):
|
||||
if sx_truthy(((type_of(val) == 'component') if sx_truthy((type_of(val) == 'component')) else (type_of(val) == 'island'))):
|
||||
for ref in scan_refs(component_body(val)):
|
||||
transitive_deps_walk(ref, seen, env)
|
||||
return NIL
|
||||
@@ -2780,7 +2780,7 @@ def transitive_deps(name, env):
|
||||
def compute_all_deps(env):
|
||||
for name in env_components(env):
|
||||
val = env_get(env, name)
|
||||
if sx_truthy((type_of(val) == 'component')):
|
||||
if sx_truthy(((type_of(val) == 'component') if sx_truthy((type_of(val) == 'component')) else (type_of(val) == 'island'))):
|
||||
component_set_deps(val, transitive_deps(name, env))
|
||||
return NIL
|
||||
|
||||
|
||||
@@ -36,6 +36,13 @@
|
||||
(defcomp ~dep-island ()
|
||||
(div "no deps"))
|
||||
|
||||
;; Islands with dependencies — defisland bodies must be scanned
|
||||
(defisland ~dep-island-with-child ()
|
||||
(div (~dep-leaf) "island content"))
|
||||
|
||||
(defisland ~dep-island-with-chain ()
|
||||
(div (~dep-branch) "deep island"))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; 1. scan-refs — finds component references in AST nodes
|
||||
@@ -145,6 +152,15 @@
|
||||
|
||||
(deftest "accepts name without tilde"
|
||||
(let ((deps (transitive-deps "dep-branch" (test-env))))
|
||||
(assert-contains "~dep-leaf" deps)))
|
||||
|
||||
(deftest "island direct dep scanned"
|
||||
(let ((deps (transitive-deps "~dep-island-with-child" (test-env))))
|
||||
(assert-contains "~dep-leaf" deps)))
|
||||
|
||||
(deftest "island transitive deps scanned"
|
||||
(let ((deps (transitive-deps "~dep-island-with-chain" (test-env))))
|
||||
(assert-contains "~dep-branch" deps)
|
||||
(assert-contains "~dep-leaf" deps))))
|
||||
|
||||
|
||||
@@ -173,7 +189,13 @@
|
||||
(deftest "handles multiple top-level components"
|
||||
(let ((needed (components-needed "(div (~dep-leaf) (~dep-island))" (test-env))))
|
||||
(assert-contains "~dep-leaf" needed)
|
||||
(assert-contains "~dep-island" needed))))
|
||||
(assert-contains "~dep-island" needed)))
|
||||
|
||||
(deftest "island deps included in page bundle"
|
||||
(let ((needed (components-needed "(~dep-island-with-chain)" (test-env))))
|
||||
(assert-contains "~dep-island-with-chain" needed)
|
||||
(assert-contains "~dep-branch" needed)
|
||||
(assert-contains "~dep-leaf" needed))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
@@ -476,10 +476,12 @@
|
||||
(classes (map (fn (r) (get r "cls")) valid))
|
||||
(rules (map (fn (r) (get r "rule")) valid))
|
||||
(_ (for-each (fn (rule) (collect! "cssx" rule)) rules)))
|
||||
;; Return spread: injects class + data-tw onto parent element
|
||||
(if (empty? classes)
|
||||
nil
|
||||
(make-spread {"class" (join " " classes)
|
||||
;; Return spread: injects class + data-tw onto parent element.
|
||||
;; The if is inside make-spread's arg so it goes through eval-expr
|
||||
;; (not render-to-dom), avoiding reactive-if wrapping in islands.
|
||||
(make-spread (if (empty? classes)
|
||||
{}
|
||||
{"class" (join " " classes)
|
||||
"data-tw" (or tokens "")}))))
|
||||
|
||||
|
||||
|
||||
@@ -113,6 +113,17 @@ class TestTransitiveDeps:
|
||||
deps = transitive_deps("~card", env)
|
||||
assert "~unknown" in deps
|
||||
|
||||
def test_island_deps_scanned(self):
|
||||
"""Island bodies must be scanned for component dependencies."""
|
||||
env = make_env(
|
||||
'(defcomp ~leaf (&key) (span "leaf"))',
|
||||
'(defcomp ~branch (&key) (div (~leaf)))',
|
||||
'(defisland ~my-island () (div (~branch) "island"))',
|
||||
)
|
||||
deps = transitive_deps("~my-island", env)
|
||||
assert "~branch" in deps
|
||||
assert "~leaf" in deps
|
||||
|
||||
def test_without_tilde_prefix(self):
|
||||
env = make_env(
|
||||
'(defcomp ~card (&key) (div (~shared:misc/badge)))',
|
||||
|
||||
@@ -705,6 +705,21 @@ class TestParityDeps:
|
||||
ref_d = ref_env[key].deps
|
||||
assert set(hw_d) == set(ref_d), f"Deps mismatch for {key}"
|
||||
|
||||
def test_transitive_deps_island(self):
|
||||
"""Island bodies must be scanned for component deps."""
|
||||
from shared.sx.deps import _transitive_deps_fallback
|
||||
from shared.sx.ref.sx_ref import transitive_deps as ref_td
|
||||
hw_env, ref_env = self._make_envs(
|
||||
'(defcomp ~leaf (&key) (span "leaf"))',
|
||||
'(defcomp ~branch (&key) (div (~leaf)))',
|
||||
'(defisland ~my-island () (div (~branch) "island content"))',
|
||||
)
|
||||
hw_deps = _transitive_deps_fallback("~my-island", hw_env)
|
||||
ref_deps = set(ref_td("~my-island", ref_env))
|
||||
assert hw_deps == ref_deps
|
||||
assert "~branch" in ref_deps
|
||||
assert "~leaf" in ref_deps
|
||||
|
||||
def test_scan_components_from_sx(self):
|
||||
from shared.sx.deps import _scan_components_from_sx_fallback
|
||||
from shared.sx.ref.sx_ref import scan_components_from_source as ref_sc
|
||||
|
||||
Reference in New Issue
Block a user