Bootstrap stores + event bridge, add island hydration to boot.sx

- signals.sx: fix has? → has-key?, add def-store/use-store/clear-stores
  (L3 named stores), emit-event/on-event/bridge-event (event bridge)
- boot.sx: add sx-hydrate-islands, hydrate-island, dispose-island
  for client-side island hydration from SSR output
- bootstrap_js.py: add RENAMES, platform fns (domListen, eventDetail,
  domGetData, jsonParse), public API exports for all new functions
- bootstrap_py.py: add RENAMES, server-side no-op stubs for DOM events
- Regenerate sx-ref.js (with boot adapter) and sx_ref.py
- Update reactive-islands status: hydration, stores, bridge all spec'd

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 11:13:18 +00:00
parent 5b70cd5cfc
commit c55f0956bc
7 changed files with 633 additions and 33 deletions

View File

@@ -165,6 +165,13 @@ class JSEmitter:
"*batch-depth*": "_batchDepth",
"*batch-queue*": "_batchQueue",
"*island-scope*": "_islandScope",
"*store-registry*": "_storeRegistry",
"def-store": "defStore",
"use-store": "useStore",
"clear-stores": "clearStores",
"emit-event": "emitEvent",
"on-event": "onEvent",
"bridge-event": "bridgeEvent",
"macro?": "isMacro",
"primitive?": "isPrimitive",
"get-primitive": "getPrimitive",
@@ -314,6 +321,8 @@ class JSEmitter:
"dom-add-class": "domAddClass",
"dom-remove-class": "domRemoveClass",
"dom-dispatch": "domDispatch",
"dom-listen": "domListen",
"event-detail": "eventDetail",
"dom-query": "domQuery",
"dom-query-all": "domQueryAll",
"dom-tag-name": "domTagName",
@@ -322,6 +331,8 @@ class JSEmitter:
"dom-child-nodes": "domChildNodes",
"dom-remove-children-after": "domRemoveChildrenAfter",
"dom-set-data": "domSetData",
"dom-get-data": "domGetData",
"json-parse": "jsonParse",
"dict-has?": "dictHas",
"dict-delete!": "dictDelete",
"process-bindings": "processBindings",
@@ -508,6 +519,9 @@ class JSEmitter:
"process-component-script": "processComponentScript",
"SX_VERSION": "SX_VERSION",
"boot-init": "bootInit",
"sx-hydrate-islands": "sxHydrateIslands",
"hydrate-island": "hydrateIsland",
"dispose-island": "disposeIsland",
"resolve-suspense": "resolveSuspense",
"resolve-mount-target": "resolveMountTarget",
"sx-render-with-env": "sxRenderWithEnv",
@@ -2870,6 +2884,16 @@ PLATFORM_DOM_JS = """
return el.dispatchEvent(evt);
}
function domListen(el, name, handler) {
if (!_hasDom || !el) return function() {};
el.addEventListener(name, handler);
return function() { el.removeEventListener(name, handler); };
}
function eventDetail(e) {
return (e && e.detail != null) ? e.detail : nil;
}
function domQuery(sel) {
return _hasDom ? document.querySelector(sel) : null;
}
@@ -2897,6 +2921,12 @@ PLATFORM_DOM_JS = """
function domSetData(el, key, val) {
if (el) { if (!el._sxData) el._sxData = {}; el._sxData[key] = val; }
}
function domGetData(el, key) {
return (el && el._sxData) ? (el._sxData[key] != null ? el._sxData[key] : nil) : nil;
}
function jsonParse(s) {
try { return JSON.parse(s); } catch(e) { return {}; }
}
// =========================================================================
// Performance overrides — replace transpiled spec with imperative JS
@@ -4142,6 +4172,8 @@ def public_api_js(has_html, has_sx, has_dom, has_engine, has_orch, has_boot, has
api_lines.append(' renderComponent: typeof sxRenderComponent === "function" ? sxRenderComponent : null,')
api_lines.append(' getEnv: function() { return componentEnv; },')
api_lines.append(' resolveSuspense: typeof resolveSuspense === "function" ? resolveSuspense : null,')
api_lines.append(' hydrateIslands: typeof sxHydrateIslands === "function" ? sxHydrateIslands : null,')
api_lines.append(' disposeIsland: typeof disposeIsland === "function" ? disposeIsland : null,')
api_lines.append(' init: typeof bootInit === "function" ? bootInit : null,')
elif has_orch:
api_lines.append(' init: typeof engineInit === "function" ? engineInit : null,')
@@ -4178,6 +4210,12 @@ def public_api_js(has_html, has_sx, has_dom, has_engine, has_orch, has_boot, has
api_lines.append(' batch: batch,')
api_lines.append(' isSignal: isSignal,')
api_lines.append(' makeSignal: makeSignal,')
api_lines.append(' defStore: defStore,')
api_lines.append(' useStore: useStore,')
api_lines.append(' clearStores: clearStores,')
api_lines.append(' emitEvent: emitEvent,')
api_lines.append(' onEvent: onEvent,')
api_lines.append(' bridgeEvent: bridgeEvent,')
api_lines.append(f' _version: "{version}"')
api_lines.append(' };')
api_lines.append('')