Guard all appendChild calls against spread values

The previous fix only guarded domAppend/domInsertAfter, but many
platform JS functions (asyncRenderChildren, asyncRenderElement,
asyncRenderMap, render, sxRenderWithEnv) call appendChild directly.

Add _spread guards to all direct appendChild sites. For async element
rendering, merge spread attrs onto parent (class/style join, others
overwrite) matching the sync adapter behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 03:41:07 +00:00
parent 9284a946ba
commit f52b9e880b
2 changed files with 46 additions and 14 deletions

View File

@@ -14,7 +14,7 @@
// =========================================================================
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
var SX_VERSION = "2026-03-13T03:34:17Z";
var SX_VERSION = "2026-03-13T03:40:30Z";
function isNil(x) { return x === NIL || x === null || x === undefined; }
function isSxTruthy(x) { return x !== false && !isNil(x); }
@@ -5526,7 +5526,7 @@ return (isSxTruthy((_batchDepth == 0)) ? (function() {
var frag = document.createDocumentFragment();
for (var i = 0; i < exprs.length; i++) {
var node = renderToDom(exprs[i], env, null);
if (node) frag.appendChild(node);
if (node && !node._spread) frag.appendChild(node);
}
return frag;
}
@@ -6004,7 +6004,7 @@ return (isSxTruthy((_batchDepth == 0)) ? (function() {
else ph.parentNode.removeChild(ph);
}));
})(placeholder);
} else if (result) {
} else if (result && !result._spread) {
frag.appendChild(result);
}
}
@@ -6058,7 +6058,23 @@ return (isSxTruthy((_batchDepth == 0)) ? (function() {
}));
})(placeholder);
} else if (child) {
el.appendChild(child);
if (child._spread) {
// Spread: merge attrs onto parent element
var sa = child.attrs || {};
for (var sk in sa) {
if (sk === "class") {
var ec = el.getAttribute("class") || "";
el.setAttribute("class", ec ? ec + " " + sa[sk] : sa[sk]);
} else if (sk === "style") {
var es = el.getAttribute("style") || "";
el.setAttribute("style", es ? es + ";" + sa[sk] : sa[sk]);
} else {
el.setAttribute(sk, String(sa[sk]));
}
}
} else {
el.appendChild(child);
}
}
}
}
@@ -6225,7 +6241,7 @@ return (isSxTruthy((_batchDepth == 0)) ? (function() {
var ph = document.createComment("async");
frag.appendChild(ph);
(function(p) { pending.push(result.then(function(n) { if (n) p.parentNode.replaceChild(n, p); else p.parentNode.removeChild(p); })); })(ph);
} else if (result) {
} else if (result && !result._spread) {
frag.appendChild(result);
}
}
@@ -6265,7 +6281,7 @@ return (isSxTruthy((_batchDepth == 0)) ? (function() {
var ph = document.createComment("async");
frag.appendChild(ph);
(function(p) { pending.push(result.then(function(n) { if (n) p.parentNode.replaceChild(n, p); else p.parentNode.removeChild(p); })); })(ph);
} else if (result) {
} else if (result && !result._spread) {
frag.appendChild(result);
}
}
@@ -6441,7 +6457,7 @@ return (isSxTruthy((_batchDepth == 0)) ? (function() {
}
var exprs = parse(source);
var frag = document.createDocumentFragment();
for (var i = 0; i < exprs.length; i++) frag.appendChild(renderToDom(exprs[i], merge(componentEnv), null));
for (var i = 0; i < exprs.length; i++) { var _r = renderToDom(exprs[i], merge(componentEnv), null); if (_r && !_r._spread) frag.appendChild(_r); }
return frag;
}