3 Commits

Author SHA1 Message Date
0a5562243b Fix renderComponentDOM: route render-only forms through renderDOM
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m19s
The previous fix eagerly evaluated all kwarg expressions via sxEval,
which broke render-only forms (<>, raw!, HTML tags, ~components) that
only exist in the render pipeline. Now detect render expressions by
checking if the head symbol is an HTML/SVG tag, <>, raw!, or ~component,
and route those through renderDOM while data expressions still go
through sxEval for correct scope resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:45:43 +00:00
2b41aaa6ce Fix renderComponentDOM evaluating kwarg expressions in wrong scope
renderComponentDOM was deferring evaluation of complex expressions
(arrays) passed as component kwargs, storing raw AST instead.  When the
component body later used these values as attributes, the caller's env
(with lambda params like t, a) was no longer available, producing
stringified arrays like "get,t,src" as attribute values — which browsers
interpreted as relative URLs.

Evaluate all non-literal kwarg values eagerly in the caller's env,
matching the behavior of callComponent and the Python-side renderer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:40:50 +00:00
cfe66e5342 Fix back_populates typo in Post.authors relationship
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:36:18 +00:00
2 changed files with 21 additions and 7 deletions

View File

@@ -118,7 +118,7 @@ class Post(Base):
secondary="post_authors",
primaryjoin="Post.id==post_authors.c.post_id",
secondaryjoin="Author.id==post_authors.c.author_id",
back_populates="authors",
back_populates="posts",
order_by="PostAuthor.sort_order",
)

View File

@@ -808,18 +808,32 @@
return renderDOM(fn.body, local);
}
/** True when the array expr is a render-only form (HTML tag, <>, raw!, ~comp). */
function _isRenderExpr(v) {
if (!Array.isArray(v) || !v.length) return false;
var h = v[0];
if (!isSym(h)) return false;
var n = h.name;
return !!(HTML_TAGS[n] || SVG_TAGS[n] || n === "<>" || n === "raw!" || n.charAt(0) === "~");
}
function renderComponentDOM(comp, args, env) {
var kwargs = {}, children = [];
var i = 0;
while (i < args.length) {
if (isKw(args[i]) && i + 1 < args.length) {
// Keep kwarg values as AST — renderDOM will handle them when the
// component body references the param symbol. Simple literals are
// eval'd so strings/numbers resolve immediately.
// Evaluate kwarg values eagerly in the caller's env so expressions
// like (get t "src") resolve while lambda params are still bound.
// Render-only forms (HTML tags, <>, ~comp) go through renderDOM instead.
var v = args[i + 1];
kwargs[args[i].name] = (typeof v === "string" || typeof v === "number" ||
typeof v === "boolean" || isNil(v) || isKw(v))
? v : (isSym(v) ? sxEval(v, env) : v);
if (typeof v === "string" || typeof v === "number" ||
typeof v === "boolean" || isNil(v)) {
kwargs[args[i].name] = v;
} else if (_isRenderExpr(v)) {
kwargs[args[i].name] = renderDOM(v, env);
} else {
kwargs[args[i].name] = sxEval(v, env);
}
i += 2;
} else {
children.push(args[i]);