Fix aser server-affinity expansion: keyword values, OOB wrapper, page helpers
Three bugs in aser-expand-component (adapter-sx.sx):
- Keyword values were eval'd (eval-expr can't handle <>, HTML tags);
now asered, matching the aser's rendering capabilities
- Missing default nil binding for unset &key params (caused
"Undefined symbol" errors for optional params like header-rows)
- aserCall string-quoted keyword values that were already serialized
SX — now inlines values starting with "(" directly
Server-affinity annotations for layout/nav shells:
- ~shared:layout/app-body, ~shared:layout/oob-sx — page structure
- ~layouts/nav-sibling-row, ~layouts/nav-children — server-side data
- ~layouts/doc already had :affinity :server
- ~cssx/flush marked :affinity :client (browser-only state)
Navigation fix: restore oob_page_sx wrapper for HTMX responses
so #main-panel section exists for sx-select/sx-swap targeting.
OCaml bridge: lazy page helper injection into kernel via IO proxy
(define name (fn (...) (helper "name" ...))) — enables aser_slot
to evaluate highlight/component-source etc. via coroutine bridge.
Playwright tests: added pageerror listener to test_no_console_errors,
new test_navigate_from_home_to_geography for HTMX nav regression.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,4 +33,5 @@ def _load_sx_page_files() -> None:
|
||||
# helper is registered as an IO primitive in primitives_io.py,
|
||||
# intercepted by async_eval before hitting the CEK machine.
|
||||
import logging; logging.getLogger("sx.pages").info("Injected %d page helpers as primitives: %s", len(helpers), list(helpers.keys())[:5])
|
||||
|
||||
load_page_dir(os.path.dirname(__file__), "sx")
|
||||
|
||||
@@ -194,14 +194,24 @@ async def eval_sx_url(raw_path: str) -> Any:
|
||||
]
|
||||
|
||||
try:
|
||||
content_sx = await _eval_slot(wrapped_ast, env, ctx)
|
||||
import os as _os
|
||||
if _os.environ.get("SX_USE_OCAML") == "1":
|
||||
from shared.sx.ocaml_bridge import get_bridge
|
||||
from shared.sx.parser import serialize
|
||||
from shared.sx.types import SxExpr
|
||||
bridge = await get_bridge()
|
||||
sx_text = serialize(wrapped_ast)
|
||||
ocaml_ctx = {"_helper_service": "sx"}
|
||||
content_sx = SxExpr(await bridge.aser(sx_text, ctx=ocaml_ctx))
|
||||
else:
|
||||
content_sx = await _eval_slot(wrapped_ast, env, ctx)
|
||||
except Exception as e:
|
||||
logger.error("SX URL render failed for %s: %s", raw_path, e, exc_info=True)
|
||||
return None
|
||||
|
||||
# Return response — Python wraps in page shell (CSS, scripts, headers)
|
||||
if is_htmx_request():
|
||||
return sx_response(content_sx)
|
||||
return sx_response(await oob_page_sx(content=content_sx))
|
||||
else:
|
||||
tctx = await get_template_context()
|
||||
html = await full_page_sx(tctx, header_rows="", content=content_sx)
|
||||
|
||||
Reference in New Issue
Block a user