SX request handler + AJAX nav + shared JIT globals + shell cleanup

- Remove prism.js, sweetalert2, body.js, sx-browser.js from shell —
  only WASM kernel (sx_browser.bc.wasm.js + sx-platform.js) loads
- Restore request-handler.sx integration: SX handles routing + AJAX
  detection, OCaml does aser → SSR → shell render pipeline
- AJAX fragment support: SX-Request header returns content fragment
  (~14KB) instead of full page (~858KB), cached with "ajax:" prefix
- Fix language/applications/etc page functions to return empty fragment
  instead of nil (was causing 404s)
- Shared JIT VM globals: env_bind hook mirrors ALL bindings to a single
  shared globals table — eliminates stale-snapshot class of JIT bugs
- Add native `parse` function for components that need SX parsing
- Clean up unused shell params (sx-js-hash, body-js-hash, head-scripts,
  body-scripts, use-wasm) from shell.sx, helpers.py, and server.ml

14/32 Playwright tests pass (navigation, SSR, isomorphic, geography).
Remaining failures are client-side (WASM bytecode 404s block hydration).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 03:03:57 +00:00
parent 847d04d4ba
commit 671d19c978
5 changed files with 246 additions and 307 deletions

View File

@@ -883,16 +883,11 @@ def _get_shell_static() -> dict[str, Any]:
pages_sx=pages_sx,
sx_css=sx_css,
sx_css_classes=sx_css_classes,
sx_js_hash=_script_hash("sx-browser.js"),
body_js_hash=_script_hash("body.js"),
wasm_hash=_wasm_hash("sx_browser.bc.js"),
asset_url=_ca.config.get("ASSET_URL", "/static"),
head_scripts=_shell_cfg.get("head_scripts"),
inline_css=_shell_cfg.get("inline_css"),
inline_head_js=_shell_cfg.get("inline_head_js"),
init_sx=_shell_cfg.get("init_sx"),
body_scripts=_shell_cfg.get("body_scripts"),
use_wasm=os.environ.get("SX_USE_WASM") == "1",
)
t1 = time.monotonic()
@@ -1037,8 +1032,7 @@ def sx_page_streaming_parts(ctx: dict, page_html: str, *,
from quart import current_app
pages_sx = _build_pages_sx(current_app.name)
sx_js_hash = _script_hash("sx-browser.js")
body_js_hash = _script_hash("body.js")
wasm_hash = _wasm_hash("sx_browser.bc.js")
# Shell: head + body with server-rendered HTML (not SX mount script)
shell = (
@@ -1053,11 +1047,6 @@ def sx_page_streaming_parts(ctx: dict, page_html: str, *,
f'<meta name="csrf-token" content="{_html_escape(csrf)}">\n'
f'<style id="sx-css">{sx_css}</style>\n'
f'<meta name="sx-css-classes" content="{sx_css_classes}">\n'
'<script src="https://unpkg.com/prismjs/prism.js"></script>\n'
'<script src="https://unpkg.com/prismjs/components/prism-javascript.min.js"></script>\n'
'<script src="https://unpkg.com/prismjs/components/prism-python.min.js"></script>\n'
'<script src="https://unpkg.com/prismjs/components/prism-bash.min.js"></script>\n'
'<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>\n'
"<script>if(matchMedia('(hover:hover) and (pointer:fine)').matches){document.documentElement.classList.add('hover-capable')}</script>\n"
"<script>document.addEventListener('click',function(e){var t=e.target.closest('[data-close-details]');if(!t)return;var d=t.closest('details');if(d)d.removeAttribute('open')})</script>\n"
'<style>\n'
@@ -1084,11 +1073,8 @@ def sx_page_streaming_parts(ctx: dict, page_html: str, *,
# Tail: bootstrap suspense resolver + scripts + close
tail = (
_SX_STREAMING_BOOTSTRAP + '\n'
+ (f'<script src="{asset_url}/wasm/sx_browser.bc.wasm.js"></script>\n'
f'<script src="{asset_url}/wasm/sx-platform.js"></script>\n'
if os.environ.get("SX_USE_WASM") == "1" else
f'<script src="{asset_url}/scripts/sx-browser.js?v={sx_js_hash}"></script>\n')
+ f'<script src="{asset_url}/scripts/body.js?v={body_js_hash}"></script>\n'
+ f'<script src="{asset_url}/wasm/sx_browser.bc.wasm.js?v={wasm_hash}"></script>\n'
f'<script src="{asset_url}/wasm/sx-platform.js?v={wasm_hash}"></script>\n'
)
return shell, tail