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>
Add page-render-plan to deps.sx: given page source + env + IO names,
computes a dict mapping each needed component to "server" or "client",
with server/client lists and IO dep collection. 5 new spec tests.
Integration:
- PageDef.render_plan field caches the plan at registration
- compute_page_render_plans() called from auto_mount_pages()
- Client page registry includes :render-plan per page
- Affinity demo page shows per-page render plans
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add :affinity :client/:server/:auto annotations to defcomp, with
render-target function combining affinity + IO analysis. Includes
spec (eval.sx, deps.sx), tests, Python evaluator, and demo page.
Fix critical bug: Python SX parser _ESCAPE_MAP was missing \r and \0,
causing bootstrapped JS parser to treat 'r' as whitespace — breaking
all client-side SX parsing. Also add \0 to JS string emitter and
fix serializer round-tripping for \r and \0.
Reserved word escaping: bootstrappers now auto-append _ to identifiers
colliding with JS/Python reserved words (e.g. default → default_,
final → final_), so the spec never needs to avoid host language keywords.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>