Fix component body serialization: capture ALL body expressions
defcomp/defisland with multi-expression bodies (let, letrec, freeze-scope, effect) had only the LAST expression stored as body. The browser received a truncated defisland missing let/letrec/signal bindings, causing "Undefined symbol: code-tokens" on hydration. Fix: body_exprs = expr[body_start:], wrapped in (begin ...) if multiple. Also clear stale pickle cache on code changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,11 @@ _COMPONENT_HASH: str = ""
|
|||||||
# available for client-side evaluation (e.g. cssx colour/spacing functions).
|
# available for client-side evaluation (e.g. cssx colour/spacing functions).
|
||||||
_CLIENT_LIBRARY_SOURCES: list[str] = []
|
_CLIENT_LIBRARY_SOURCES: list[str] = []
|
||||||
|
|
||||||
|
# Raw source text per component name — used to send the ORIGINAL source
|
||||||
|
# to the browser instead of re-serializing the evaluated AST (which loses
|
||||||
|
# let/letrec/signal bindings that the client needs for hydration).
|
||||||
|
_COMPONENT_RAW_SOURCE: dict[str, str] = {}
|
||||||
|
|
||||||
|
|
||||||
def get_component_env() -> dict[str, Any]:
|
def get_component_env() -> dict[str, Any]:
|
||||||
"""Return the shared component environment."""
|
"""Return the shared component environment."""
|
||||||
@@ -456,10 +461,19 @@ def register_components(sx_source: str, *, _defer_postprocess: bool = False) ->
|
|||||||
if name and expr[0].name in ("defcomp", "defisland"):
|
if name and expr[0].name in ("defcomp", "defisland"):
|
||||||
params, has_children = _parse_defcomp_params(expr[2] if len(expr) > 3 else [])
|
params, has_children = _parse_defcomp_params(expr[2] if len(expr) > 3 else [])
|
||||||
cls = Island if expr[0].name == "defisland" else Component
|
cls = Island if expr[0].name == "defisland" else Component
|
||||||
|
# Body may be multiple expressions (let, letrec, freeze-scope, etc.)
|
||||||
|
# Skip name + params; also skip :effects keyword pair if present
|
||||||
|
body_start = 3
|
||||||
|
if (len(expr) > 4
|
||||||
|
and hasattr(expr[3], 'name')
|
||||||
|
and isinstance(expr[3], Keyword)):
|
||||||
|
body_start = 5 # skip :effects [list]
|
||||||
|
body_exprs = expr[body_start:]
|
||||||
|
body = body_exprs[0] if len(body_exprs) == 1 else [Symbol("begin")] + body_exprs
|
||||||
_COMPONENT_ENV[name] = cls(
|
_COMPONENT_ENV[name] = cls(
|
||||||
name=name.lstrip("~"),
|
name=name.lstrip("~"),
|
||||||
params=params, has_children=has_children,
|
params=params, has_children=has_children,
|
||||||
body=expr[-1], closure={},
|
body=body, closure={},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-scan CSS classes for newly registered components.
|
# Pre-scan CSS classes for newly registered components.
|
||||||
|
|||||||
Reference in New Issue
Block a user