Fix reactive islands client-side navigation and hydration
Three bugs prevented islands from working during SX wire navigation: 1. components_for_request() only bundled Component and Macro defs, not Island defs — client never received defisland definitions during navigation (components_for_page for initial HTML shell was correct). 2. hydrate-island used morph-children which can't transfer addEventListener event handlers from freshly rendered DOM to existing nodes. Changed to clear+append so reactive DOM with live signal subscriptions is inserted directly. 3. asyncRenderToDom (client-side async page eval) checked _component but not _island on ~-prefixed names — islands fell through to generic eval which failed. Now delegates to renderDomIsland. 4. setInterval_/setTimeout_ passed SX Lambda objects directly to native timers. JS coerced them to "[object Object]" and tried to eval as code, causing "missing ] after element list". Added _wrapSxFn to convert SX lambdas to JS functions before passing to timers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -473,7 +473,7 @@ def components_for_request(source: str = "",
|
||||
from quart import request
|
||||
from .jinja_bridge import _COMPONENT_ENV
|
||||
from .deps import components_needed
|
||||
from .types import Component, Macro
|
||||
from .types import Component, Island, Macro
|
||||
from .parser import serialize
|
||||
|
||||
# Determine which components the page needs
|
||||
@@ -493,7 +493,19 @@ def components_for_request(source: str = "",
|
||||
|
||||
parts = []
|
||||
for key, val in _COMPONENT_ENV.items():
|
||||
if isinstance(val, Component):
|
||||
if isinstance(val, Island):
|
||||
comp_name = f"~{val.name}"
|
||||
if needed is not None and comp_name not in needed and key not in needed:
|
||||
continue
|
||||
if comp_name in loaded or val.name in loaded:
|
||||
continue
|
||||
param_strs = ["&key"] + list(val.params)
|
||||
if val.has_children:
|
||||
param_strs.extend(["&rest", "children"])
|
||||
params_sx = "(" + " ".join(param_strs) + ")"
|
||||
body_sx = serialize(val.body, pretty=True)
|
||||
parts.append(f"(defisland ~{val.name} {params_sx} {body_sx})")
|
||||
elif isinstance(val, Component):
|
||||
comp_name = f"~{val.name}"
|
||||
# Skip if not needed for this page
|
||||
if needed is not None and comp_name not in needed and key not in needed:
|
||||
|
||||
Reference in New Issue
Block a user