Try-first routing: attempt eval, fall back on failure
Remove strict deps check — for case expressions like essay pages, deps includes ALL branches but only one is taken. Instead, just try to eval the content. If a component is missing, tryEvalContent catches the error and we transparently fall back to server fetch. deps field remains in registry for future prefetching use. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
// =========================================================================
|
||||
|
||||
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
|
||||
var SX_VERSION = "2026-03-06T22:06:19Z";
|
||||
var SX_VERSION = "2026-03-06T22:10:27Z";
|
||||
|
||||
function isNil(x) { return x === NIL || x === null || x === undefined; }
|
||||
function isSxTruthy(x) { return x !== false && !isNil(x); }
|
||||
@@ -1932,32 +1932,21 @@ return forEach(function(form) { return (isSxTruthy((isSxTruthy(!isSxTruthy(isPro
|
||||
return bindBoostForm(form, method, action);
|
||||
})()) : NIL); }, domQueryAll(container, "form")); };
|
||||
|
||||
// has-all-deps?
|
||||
var hasAllDeps_p = function(deps) { return (function() {
|
||||
var loaded = loadedComponentNames();
|
||||
var missing = false;
|
||||
{ var _c = deps; for (var _i = 0; _i < _c.length; _i++) { var dep = _c[_i]; if (isSxTruthy(!isSxTruthy(contains(loaded, dep)))) {
|
||||
missing = dep;
|
||||
} } }
|
||||
return (isSxTruthy(missing) ? (logInfo((String("sx:route missing component ") + String(missing))), false) : true);
|
||||
})(); };
|
||||
|
||||
// try-client-route
|
||||
var tryClientRoute = function(pathname) { return (function() {
|
||||
var match = findMatchingRoute(pathname, _pageRoutes);
|
||||
return (isSxTruthy(isNil(match)) ? (logInfo((String("sx:route no match (") + String(len(_pageRoutes)) + String(" routes) ") + String(pathname))), false) : (isSxTruthy(get(match, "has-data")) ? (logInfo((String("sx:route server (has data) ") + String(pathname))), false) : (function() {
|
||||
var contentSrc = get(match, "content");
|
||||
var deps = sxOr(get(match, "deps"), []);
|
||||
var closure = sxOr(get(match, "closure"), {});
|
||||
var params = get(match, "params");
|
||||
return (isSxTruthy(sxOr(isNil(contentSrc), isEmpty(contentSrc))) ? (logWarn((String("sx:route no content for ") + String(pathname))), false) : (isSxTruthy(!isSxTruthy(hasAllDeps_p(deps))) ? (logInfo((String("sx:route server (missing deps) ") + String(pathname))), false) : (function() {
|
||||
return (isSxTruthy(sxOr(isNil(contentSrc), isEmpty(contentSrc))) ? (logWarn((String("sx:route no content for ") + String(pathname))), false) : (function() {
|
||||
var env = merge(closure, params);
|
||||
var rendered = tryEvalContent(contentSrc, env);
|
||||
return (isSxTruthy(isNil(rendered)) ? (logWarn((String("sx:route eval failed for ") + String(pathname))), false) : (function() {
|
||||
return (isSxTruthy(isNil(rendered)) ? (logInfo((String("sx:route server (eval failed) ") + String(pathname))), false) : (function() {
|
||||
var target = domQueryById("main-panel");
|
||||
return (isSxTruthy(isNil(target)) ? (logWarn("sx:route #main-panel not found"), false) : (domSetTextContent(target, ""), domAppend(target, rendered), hoistHeadElementsFull(target), processElements(target), sxHydrateElements(target), logInfo((String("sx:route client ") + String(pathname))), true));
|
||||
})());
|
||||
})()));
|
||||
})());
|
||||
})()));
|
||||
})(); };
|
||||
|
||||
|
||||
@@ -543,42 +543,26 @@
|
||||
;; Client-side routing
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define has-all-deps?
|
||||
(fn (deps)
|
||||
;; Check if all component deps are loaded in the client env.
|
||||
;; deps is a list of component name strings (e.g. "~essay-foo").
|
||||
(let ((loaded (loaded-component-names))
|
||||
(missing false))
|
||||
(for-each
|
||||
(fn (dep)
|
||||
(when (not (contains? loaded dep))
|
||||
(set! missing dep)))
|
||||
deps)
|
||||
(if missing
|
||||
(do (log-info (str "sx:route missing component " missing)) false)
|
||||
true))))
|
||||
|
||||
(define try-client-route
|
||||
(fn (pathname)
|
||||
;; Try to render a page client-side. Returns true if successful, false otherwise.
|
||||
;; Only works for pages without :data dependencies and with all deps loaded.
|
||||
;; Only works for pages without :data dependencies.
|
||||
;; Uses try-eval-content which catches errors — if a component is missing,
|
||||
;; eval fails and we fall back to server fetch transparently.
|
||||
(let ((match (find-matching-route pathname _page-routes)))
|
||||
(if (nil? match)
|
||||
(do (log-info (str "sx:route no match (" (len _page-routes) " routes) " pathname)) false)
|
||||
(if (get match "has-data")
|
||||
(do (log-info (str "sx:route server (has data) " pathname)) false)
|
||||
(let ((content-src (get match "content"))
|
||||
(deps (or (get match "deps") (list)))
|
||||
(closure (or (get match "closure") {}))
|
||||
(params (get match "params")))
|
||||
(if (or (nil? content-src) (empty? content-src))
|
||||
(do (log-warn (str "sx:route no content for " pathname)) false)
|
||||
(if (not (has-all-deps? deps))
|
||||
(do (log-info (str "sx:route server (missing deps) " pathname)) false)
|
||||
(let ((env (merge closure params))
|
||||
(rendered (try-eval-content content-src env)))
|
||||
(if (nil? rendered)
|
||||
(do (log-warn (str "sx:route eval failed for " pathname)) false)
|
||||
(let ((env (merge closure params))
|
||||
(rendered (try-eval-content content-src env)))
|
||||
(if (nil? rendered)
|
||||
(do (log-info (str "sx:route server (eval failed) " pathname)) false)
|
||||
(let ((target (dom-query-by-id "main-panel")))
|
||||
(if (nil? target)
|
||||
(do (log-warn "sx:route #main-panel not found") false)
|
||||
@@ -589,7 +573,7 @@
|
||||
(process-elements target)
|
||||
(sx-hydrate-elements target)
|
||||
(log-info (str "sx:route client " pathname))
|
||||
true)))))))))))))
|
||||
true))))))))))))
|
||||
|
||||
|
||||
(define bind-client-route-link
|
||||
|
||||
Reference in New Issue
Block a user