diff --git a/shared/static/scripts/sx-browser.js b/shared/static/scripts/sx-browser.js index dab0e5b..88ba776 100644 --- a/shared/static/scripts/sx-browser.js +++ b/shared/static/scripts/sx-browser.js @@ -14,7 +14,7 @@ // ========================================================================= var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } }); - var SX_VERSION = "2026-03-07T01:03:44Z"; + var SX_VERSION = "2026-03-07T01:13:04Z"; function isNil(x) { return x === NIL || x === null || x === undefined; } function isSxTruthy(x) { return x !== false && !isNil(x); } @@ -2049,6 +2049,13 @@ return domAppendToHead(link); }, domQueryAll(container, "link[rel=\"stylesheet\" // resolve-route-target var resolveRouteTarget = function(targetSel) { return (isSxTruthy((isSxTruthy(targetSel) && !isSxTruthy((targetSel == "true")))) ? domQuery(targetSel) : NIL); }; + // deps-satisfied? + var depsSatisfied_p = function(match) { return (function() { + var deps = get(match, "deps"); + var loaded = loadedComponentNames(); + return (isSxTruthy(sxOr(isNil(deps), isEmpty(deps))) ? true : isEvery(function(dep) { return contains(loaded, dep); }, deps)); +})(); }; + // try-client-route var tryClientRoute = function(pathname, targetSel) { return (function() { var match = findMatchingRoute(pathname, _pageRoutes); @@ -2059,7 +2066,7 @@ return domAppendToHead(link); }, domQueryAll(container, "link[rel=\"stylesheet\" var pageName = get(match, "name"); return (isSxTruthy(sxOr(isNil(contentSrc), isEmpty(contentSrc))) ? (logWarn((String("sx:route no content for ") + String(pathname))), false) : (function() { var target = resolveRouteTarget(targetSel); - return (isSxTruthy(isNil(target)) ? (logWarn((String("sx:route target not found: ") + String(targetSel))), false) : (logInfo((String("sx:route has-data=") + String(get(match, "has-data")) + String(" type=") + String(typeOf(get(match, "has-data"))) + String(" page=") + String(pageName))), (isSxTruthy(get(match, "has-data")) ? (function() { + return (isSxTruthy(isNil(target)) ? (logWarn((String("sx:route target not found: ") + String(targetSel))), false) : (isSxTruthy(!isSxTruthy(depsSatisfied_p(match))) ? (logInfo((String("sx:route deps not loaded for ") + String(pageName))), false) : (logInfo((String("sx:route has-data=") + String(get(match, "has-data")) + String(" type=") + String(typeOf(get(match, "has-data"))) + String(" page=") + String(pageName))), (isSxTruthy(get(match, "has-data")) ? (function() { var cacheKey = pageDataCacheKey(pageName, params); var cached = pageDataCacheGet(cacheKey); logInfo((String("sx:route cache-key=") + String(cacheKey) + String(" cached=") + String(!isSxTruthy(isNil(cached))))); @@ -2077,7 +2084,7 @@ return (function() { var env = merge(closure, params); var rendered = tryEvalContent(contentSrc, env); return (isSxTruthy(isNil(rendered)) ? (logInfo((String("sx:route server (eval failed) ") + String(pathname))), false) : (swapRenderedContent(target, rendered, pathname), true)); -})()))); +})())))); })()); })()); })(); }; diff --git a/shared/sx/ref/orchestration.sx b/shared/sx/ref/orchestration.sx index 183e099..465f6c3 100644 --- a/shared/sx/ref/orchestration.sx +++ b/shared/sx/ref/orchestration.sx @@ -619,6 +619,16 @@ nil))) +(define deps-satisfied? + (fn (match) + ;; Check if all component deps for a page are loaded client-side. + (let ((deps (get match "deps")) + (loaded (loaded-component-names))) + (if (or (nil? deps) (empty? deps)) + true + (every? (fn (dep) (contains? loaded dep)) deps))))) + + (define try-client-route (fn (pathname target-sel) ;; Try to render a page client-side. Returns true if successful, false otherwise. @@ -636,10 +646,12 @@ (let ((target (resolve-route-target target-sel))) (if (nil? target) (do (log-warn (str "sx:route target not found: " target-sel)) false) - (do - (log-info (str "sx:route has-data=" (get match "has-data") - " type=" (type-of (get match "has-data")) - " page=" page-name)) + (if (not (deps-satisfied? match)) + (do (log-info (str "sx:route deps not loaded for " page-name)) false) + (do + (log-info (str "sx:route has-data=" (get match "has-data") + " type=" (type-of (get match "has-data")) + " page=" page-name)) (if (get match "has-data") ;; Data page: check cache, else resolve asynchronously (let ((cache-key (page-data-cache-key page-name params)) @@ -674,7 +686,7 @@ (do (log-info (str "sx:route server (eval failed) " pathname)) false) (do (swap-rendered-content target rendered pathname) - true))))))))))))) + true)))))))))))))) (define bind-client-route-link