JIT compiler: - Fix jit_compile_lambda: resolve `compile` via symbol lookup in env instead of embedding VmClosure in AST (CEK dispatches differently) - Register eval-defcomp/eval-defisland/eval-defmacro runtime helpers in browser kernel for bytecoded defcomp forms - Disable broken .sxbc.json path (missing arity in nested code blocks), use .sxbc text format only - Mark JIT-failed closures as sentinel to stop retrying CSSX in browser: - Add cssx.sx symlink + cssx.sxbc to browser web stack - Add flush-cssx! to orchestration.sx post-swap for SPA nav - Add cssx.sx to compile-modules.js and mcp_tree.ml bytecode lists SPA navigation: - Fix double-fetch: check e.defaultPrevented in click delegation (bind-event already handled the click) - Fix layout destruction: change nav links from outerHTML to innerHTML swap (outerHTML destroyed #main-panel when response lacked it) - Guard JS popstate handler when SX engine is booted - Rename sx-platform.js → sx-platform-2.js to bust immutable cache Playwright tests: - Add trackErrors() helper to all test specs - Add SPA DOM comparison test (SPA nav vs fresh load) - Add single-fetch + no-duplicate-elements test - Improve MCP tool output: show failure details and error messages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
82 lines
3.7 KiB
Plaintext
82 lines
3.7 KiB
Plaintext
(defcomp
|
|
~shared:shell/sx-page-shell
|
|
(&key
|
|
(title :as string)
|
|
(meta-html :as string?)
|
|
(csrf :as string)
|
|
(sx-css :as string?)
|
|
(sx-css-classes :as string?)
|
|
(component-hash :as string?)
|
|
(component-defs :as string?)
|
|
(pages-sx :as string?)
|
|
(page-sx :as string?)
|
|
(body-html :as string?)
|
|
(asset-url :as string)
|
|
(wasm-hash :as string?)
|
|
(inline-css :as string?)
|
|
(inline-head-js :as string?)
|
|
(init-sx :as string?))
|
|
(<>
|
|
(raw! "<!doctype html>")
|
|
(html
|
|
:lang "en"
|
|
(head
|
|
(meta :charset "utf-8")
|
|
(meta :name "viewport" :content "width=device-width, initial-scale=1")
|
|
(meta :name "robots" :content "index,follow")
|
|
(meta :name "theme-color" :content "#ffffff")
|
|
(title title)
|
|
(when meta-html (raw! meta-html))
|
|
(meta :name "csrf-token" :content csrf)
|
|
(style :id "sx-css" (raw! (or sx-css "")))
|
|
(let
|
|
((cssx-rules (collected "cssx")))
|
|
(clear-collected! "cssx")
|
|
(when
|
|
(not (empty? cssx-rules))
|
|
(style :data-cssx true (raw! (join "" cssx-rules)))))
|
|
(meta :name "sx-css-classes" :content (or sx-css-classes ""))
|
|
(if
|
|
(not (nil? inline-head-js))
|
|
(when
|
|
(not (empty? inline-head-js))
|
|
(script (raw! inline-head-js)))
|
|
(<>
|
|
(script
|
|
(raw!
|
|
"if(matchMedia('(hover:hover) and (pointer:fine)').matches){document.documentElement.classList.add('hover-capable')}"))
|
|
(script
|
|
(raw!
|
|
"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')})"))))
|
|
(if
|
|
(not (nil? inline-css))
|
|
(style (raw! inline-css))
|
|
(style
|
|
(raw!
|
|
"details[data-toggle-group=\"mobile-panels\"]>summary{list-style:none}\ndetails[data-toggle-group=\"mobile-panels\"]>summary::-webkit-details-marker{display:none}\n@media(min-width:768px){.nav-group:focus-within .submenu,.nav-group:hover .submenu{display:block}}\nimg{max-width:100%;height:auto}\n.clamp-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n.clamp-3{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}\n.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}\ndetails.group{overflow:hidden}details.group>summary{list-style:none}details.group>summary::-webkit-details-marker{display:none}\n.sx-indicator{display:none}.sx-request .sx-indicator{display:inline-flex}\n.sx-error .sx-indicator{display:none}.sx-loading .sx-indicator{display:inline-flex}\n.js-wrap.open .js-pop{display:block}.js-wrap.open .js-backdrop{display:block}"))))
|
|
(body
|
|
:class "bg-stone-50 text-stone-900"
|
|
(div :id "sx-root" (raw! (or body-html "")))
|
|
(div :id "portal-root")
|
|
(style
|
|
(raw!
|
|
"[data-sx-island] button,[data-sx-island] a,[data-sx-island] [role=button]{cursor:pointer}"))
|
|
(script
|
|
:type "text/sx"
|
|
:data-components true
|
|
:data-hash component-hash
|
|
(raw! (or component-defs "")))
|
|
(when
|
|
init-sx
|
|
(script :type "text/sx" :data-init true (raw! init-sx)))
|
|
(script :type "text/sx-pages" (raw! (or pages-sx "")))
|
|
(script
|
|
:type "text/sx"
|
|
:data-mount "#sx-root"
|
|
(raw! (or page-sx "")))
|
|
(let
|
|
((wv (or wasm-hash "0")))
|
|
(<>
|
|
(script :src (str asset-url "/wasm/sx_browser.bc.wasm.js?v=" wv))
|
|
(script :src (str asset-url "/wasm/sx-platform-2.js?v=" wv))))))))
|