@barefootjs/cli 0.26.3 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/core/advanced/compiler-internals.md +8 -7
- package/dist/docs/core/advanced/performance.md +1 -1
- package/dist/docs/core/core-concepts/how-it-works.mdx +23 -7
- package/dist/docs/core/introduction.mdx +6 -4
- package/dist/docs/core/rendering/client-directive.md +24 -7
- package/dist/docs/core/rendering/jsx-compatibility.md +18 -1
- package/dist/index.js +761 -130
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -3695,7 +3695,7 @@ function templateAttrExpr(attrName, valExpr, presenceOrUndefined) {
|
|
|
3695
3695
|
return `\${((v) => v != null ? 'style="' + ${escapeAttrValueExpr("v")} + '"' : '')(styleToCss(${valExpr}))}`;
|
|
3696
3696
|
}
|
|
3697
3697
|
if (attrName === "data-key" || attrName.startsWith("data-key-")) {
|
|
3698
|
-
return `${attrName}="\${${valExpr}}"`;
|
|
3698
|
+
return `${attrName}="\${${escapeAttrValueExpr(valExpr)}}"`;
|
|
3699
3699
|
}
|
|
3700
3700
|
return `\${(${valExpr}) != null ? '${attrName}="' + ${escapeAttrValueExpr(valExpr)} + '"' : ''}`;
|
|
3701
3701
|
}
|
|
@@ -3815,12 +3815,54 @@ function renderPreamble(preamble, opts) {
|
|
|
3815
3815
|
if (seg.kind === "js") {
|
|
3816
3816
|
const text = opts.textVariant === "template" ? seg.templateText ?? seg.text : seg.text;
|
|
3817
3817
|
out += opts.transformJs ? opts.transformJs(text) : text;
|
|
3818
|
+
} else if (opts.rawLeaf) {
|
|
3819
|
+
out += opts.renderLeaf(escapeLeafTextExpressions(seg.ir));
|
|
3818
3820
|
} else {
|
|
3819
3821
|
out += "`" + opts.renderLeaf(escapeLeafTextExpressions(seg.ir)) + "`";
|
|
3820
3822
|
}
|
|
3821
3823
|
}
|
|
3822
3824
|
return out;
|
|
3823
3825
|
}
|
|
3826
|
+
function flatMapLeafKeyExpr(ir) {
|
|
3827
|
+
if (ir.type !== "element") return null;
|
|
3828
|
+
const keyAttr = ir.attrs.find((a) => a.name === "key");
|
|
3829
|
+
if (!keyAttr) return null;
|
|
3830
|
+
switch (keyAttr.value.kind) {
|
|
3831
|
+
case "expression":
|
|
3832
|
+
return `(${keyAttr.value.expr})`;
|
|
3833
|
+
case "literal":
|
|
3834
|
+
return JSON.stringify(keyAttr.value.value);
|
|
3835
|
+
case "template":
|
|
3836
|
+
return attrValueToString(keyAttr.value);
|
|
3837
|
+
default:
|
|
3838
|
+
return null;
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
function stripLeafKeyAttr(ir) {
|
|
3842
|
+
if (ir.type !== "element") return ir;
|
|
3843
|
+
return { ...ir, attrs: ir.attrs.filter((a) => a.name !== "key") };
|
|
3844
|
+
}
|
|
3845
|
+
function renderFlatMapClientBody(cb, restSpreadNames) {
|
|
3846
|
+
return renderPreamble(cb, {
|
|
3847
|
+
textVariant: "client",
|
|
3848
|
+
rawLeaf: true,
|
|
3849
|
+
renderLeaf: (ir) => {
|
|
3850
|
+
const key = flatMapLeafKeyExpr(ir);
|
|
3851
|
+
const html = irToHtmlTemplate(stripLeafKeyAttr(ir), restSpreadNames, 1, void 0, void 0, true);
|
|
3852
|
+
return `({ k: ${key ?? "undefined"}, h: \`${html}\` })`;
|
|
3853
|
+
}
|
|
3854
|
+
});
|
|
3855
|
+
}
|
|
3856
|
+
function flatMapCallbackHasKeyedLeaf(cb) {
|
|
3857
|
+
return cb.segments.some((s) => s.kind === "jsx" && flatMapLeafKeyExpr(s.ir) !== null);
|
|
3858
|
+
}
|
|
3859
|
+
function renderFlatMapProjectionClientBody(inner, restSpreadNames) {
|
|
3860
|
+
const chained = applyLoopChain(inner);
|
|
3861
|
+
const params = inner.index ? `(${inner.param}, ${inner.index})` : `(${inner.param})`;
|
|
3862
|
+
const key = inner.key ? `(${inner.key})` : "undefined";
|
|
3863
|
+
const html = inner.children.map((c) => irToHtmlTemplate(escapeLeafTextExpressions(c), restSpreadNames, 1, void 0, void 0, true)).join("");
|
|
3864
|
+
return `${chained}.map(${params} => ({ k: ${key}, h: \`${html}\` }))`;
|
|
3865
|
+
}
|
|
3824
3866
|
function escapeLeafTextExpressions(ir) {
|
|
3825
3867
|
switch (ir.type) {
|
|
3826
3868
|
case "element":
|
|
@@ -3884,6 +3926,10 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
|
|
|
3884
3926
|
return escapeHtml(node.value);
|
|
3885
3927
|
case "expression": {
|
|
3886
3928
|
if (node.expr === "null" || node.expr === "undefined") return "";
|
|
3929
|
+
if (node.markerless) {
|
|
3930
|
+
const bare = wrapInterpolation(wrapExpr(node.expr));
|
|
3931
|
+
return `\${${bare}}`;
|
|
3932
|
+
}
|
|
3887
3933
|
const inner = wrapInterpolation(wrapExpr(node.expr));
|
|
3888
3934
|
const valueExpr = node.joinArrayChild ? `Array.isArray(${inner}) ? ${inner}.join('') : (${inner} ?? '')` : inner;
|
|
3889
3935
|
if (node.slotId) {
|
|
@@ -3949,7 +3995,7 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
|
|
|
3949
3995
|
let mapExpr;
|
|
3950
3996
|
if (node.flatMapCallback) {
|
|
3951
3997
|
const body2 = renderPreamble(node.flatMapCallback, {
|
|
3952
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, restSpreadNames, loopDepth + 1, loopParams, branchSlotsVar, insideLoop)
|
|
3998
|
+
renderLeaf: (ir) => irToHtmlTemplate(stripLeafKeyAttr(ir), restSpreadNames, loopDepth + 1, loopParams, branchSlotsVar, insideLoop)
|
|
3953
3999
|
});
|
|
3954
4000
|
mapExpr = `\${${wrappedArray}.flatMap(${node.flatMapCallback.params} => ${body2}).join('')}`;
|
|
3955
4001
|
} else if (node.preamble) {
|
|
@@ -4200,7 +4246,8 @@ function irToPlaceholderTemplate(node, restSpreadNames, loopDepth = 0, loopParam
|
|
|
4200
4246
|
let mapExpr;
|
|
4201
4247
|
if (node.flatMapCallback) {
|
|
4202
4248
|
const body2 = renderPreamble(node.flatMapCallback, {
|
|
4203
|
-
|
|
4249
|
+
// Leaf `key` stripped — see the irToHtmlTemplate site above.
|
|
4250
|
+
renderLeaf: (ir) => irToPlaceholderTemplate(stripLeafKeyAttr(ir), restSpreadNames, loopDepth + 1, loopParams)
|
|
4204
4251
|
});
|
|
4205
4252
|
mapExpr = `\${${wrappedArray}.flatMap(${node.flatMapCallback.params} => ${body2}).join('')}`;
|
|
4206
4253
|
} else if (node.preamble) {
|
|
@@ -4698,7 +4745,7 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
4698
4745
|
case "expression":
|
|
4699
4746
|
if (node.expr === "null" || node.expr === "undefined") return "";
|
|
4700
4747
|
if (node.clientOnly && node.slotId) {
|
|
4701
|
-
return `<!--bf
|
|
4748
|
+
return `<!--bf:${node.slotId}--><!--/-->`;
|
|
4702
4749
|
}
|
|
4703
4750
|
{
|
|
4704
4751
|
const transformed = transformExpr(node.expr, node.templateExpr);
|
|
@@ -4799,7 +4846,8 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
4799
4846
|
const body2 = renderPreamble(node.flatMapCallback, {
|
|
4800
4847
|
textVariant: "template",
|
|
4801
4848
|
transformJs: (t) => applyPropsRewrite(t, propsObjectName ?? null),
|
|
4802
|
-
|
|
4849
|
+
// Leaf `key` stripped — see the irToHtmlTemplate site above.
|
|
4850
|
+
renderLeaf: (ir) => recurseInLoopBody(stripLeafKeyAttr(ir))
|
|
4803
4851
|
});
|
|
4804
4852
|
mapExpr = `\${${iterArrayExpr}.flatMap(${node.flatMapCallback.params} => ${body2}).join('')}`;
|
|
4805
4853
|
} else if (node.preamble) {
|
|
@@ -11596,6 +11644,76 @@ function checkLoopKey(callback, ctx2, isNested) {
|
|
|
11596
11644
|
return;
|
|
11597
11645
|
}
|
|
11598
11646
|
}
|
|
11647
|
+
function flatMapProjectionCall(body2) {
|
|
11648
|
+
let expr;
|
|
11649
|
+
if (ts11.isBlock(body2)) {
|
|
11650
|
+
const real = body2.statements;
|
|
11651
|
+
if (real.length !== 1 || !ts11.isReturnStatement(real[0]) || !real[0].expression) return null;
|
|
11652
|
+
expr = real[0].expression;
|
|
11653
|
+
} else {
|
|
11654
|
+
expr = body2;
|
|
11655
|
+
}
|
|
11656
|
+
while (ts11.isParenthesizedExpression(expr)) expr = expr.expression;
|
|
11657
|
+
if (!ts11.isCallExpression(expr)) return null;
|
|
11658
|
+
if (!getMapLikeMethod(expr)) return null;
|
|
11659
|
+
const cb = expr.arguments[0];
|
|
11660
|
+
if (!cb || !ts11.isArrowFunction(cb) && !ts11.isFunctionExpression(cb)) return null;
|
|
11661
|
+
for (const p of cb.parameters) {
|
|
11662
|
+
if (!ts11.isIdentifier(p.name)) return null;
|
|
11663
|
+
}
|
|
11664
|
+
let innerBody = cb.body;
|
|
11665
|
+
if (ts11.isBlock(innerBody)) {
|
|
11666
|
+
const ret = innerBody.statements.find(
|
|
11667
|
+
(s) => ts11.isReturnStatement(s) && s.expression != null
|
|
11668
|
+
);
|
|
11669
|
+
if (innerBody.statements.length !== 1 || !ret?.expression) return null;
|
|
11670
|
+
innerBody = ret.expression;
|
|
11671
|
+
}
|
|
11672
|
+
while (ts11.isParenthesizedExpression(innerBody)) innerBody = innerBody.expression;
|
|
11673
|
+
const isElementish = (n) => {
|
|
11674
|
+
let m = n;
|
|
11675
|
+
while (ts11.isParenthesizedExpression(m)) m = m.expression;
|
|
11676
|
+
if (ts11.isJsxElement(m) || ts11.isJsxSelfClosingElement(m)) return leafIsWirelessElement(m);
|
|
11677
|
+
if (ts11.isConditionalExpression(m)) return isElementish(m.whenTrue) && isElementish(m.whenFalse);
|
|
11678
|
+
return false;
|
|
11679
|
+
};
|
|
11680
|
+
if (!isElementish(innerBody)) return null;
|
|
11681
|
+
return expr;
|
|
11682
|
+
}
|
|
11683
|
+
function leafIsWirelessElement(el) {
|
|
11684
|
+
let ok = true;
|
|
11685
|
+
const visit3 = (n) => {
|
|
11686
|
+
if (!ok) return;
|
|
11687
|
+
if (ts11.isJsxOpeningElement(n) || ts11.isJsxSelfClosingElement(n)) {
|
|
11688
|
+
const tagNode = n.tagName;
|
|
11689
|
+
const isIntrinsic = ts11.isIdentifier(tagNode) ? !/^[A-Z]/.test(tagNode.text) : ts11.isJsxNamespacedName(tagNode);
|
|
11690
|
+
if (!isIntrinsic) {
|
|
11691
|
+
ok = false;
|
|
11692
|
+
return;
|
|
11693
|
+
}
|
|
11694
|
+
for (const attr of n.attributes.properties) {
|
|
11695
|
+
if (ts11.isJsxSpreadAttribute(attr)) {
|
|
11696
|
+
ok = false;
|
|
11697
|
+
return;
|
|
11698
|
+
}
|
|
11699
|
+
if (ts11.isJsxAttribute(attr)) {
|
|
11700
|
+
const name2 = attr.name.getText();
|
|
11701
|
+
if (/^on[A-Z]/.test(name2)) {
|
|
11702
|
+
ok = false;
|
|
11703
|
+
return;
|
|
11704
|
+
}
|
|
11705
|
+
}
|
|
11706
|
+
}
|
|
11707
|
+
}
|
|
11708
|
+
if (ts11.isCallExpression(n) && getMapLikeMethod(n) && containsJsxInExpression(n)) {
|
|
11709
|
+
ok = false;
|
|
11710
|
+
return;
|
|
11711
|
+
}
|
|
11712
|
+
ts11.forEachChild(n, visit3);
|
|
11713
|
+
};
|
|
11714
|
+
visit3(el);
|
|
11715
|
+
return ok;
|
|
11716
|
+
}
|
|
11599
11717
|
function loopBodyIsMultiRoot(children2) {
|
|
11600
11718
|
const real = children2.filter(
|
|
11601
11719
|
(c) => !(c.type === "text" && typeof c.value === "string" && !c.value.trim())
|
|
@@ -11641,6 +11759,7 @@ function extractItemConditionalKey(cond) {
|
|
|
11641
11759
|
}
|
|
11642
11760
|
function transformMapCall(node, ctx2, isClientOnly = false, method2 = "map") {
|
|
11643
11761
|
const isNested = ctx2.loopParams.size > 0;
|
|
11762
|
+
const diagCountAtEntry = ctx2.analyzer.errors.length;
|
|
11644
11763
|
const depth = ctx2.loopDepth;
|
|
11645
11764
|
const propAccess = node.expression;
|
|
11646
11765
|
const mapSource = propAccess.expression;
|
|
@@ -11978,12 +12097,39 @@ function transformMapCall(node, ctx2, isClientOnly = false, method2 = "map") {
|
|
|
11978
12097
|
}
|
|
11979
12098
|
}
|
|
11980
12099
|
}
|
|
11981
|
-
if (method2 === "flatMap" && children2.length === 0) {
|
|
12100
|
+
if (method2 === "flatMap" && children2.length === 0 && !flatMapProjectionCall(body2)) {
|
|
11982
12101
|
flatMapCallback = buildFlatMapCallback(callback, body2, ctx2);
|
|
11983
12102
|
}
|
|
11984
12103
|
} else {
|
|
11985
12104
|
tryTransformRenderableBody(body2);
|
|
11986
12105
|
}
|
|
12106
|
+
if (method2 === "flatMap" && children2.length === 0 && !flatMapCallback) {
|
|
12107
|
+
const projection = flatMapProjectionCall(body2);
|
|
12108
|
+
if (projection) {
|
|
12109
|
+
const transformed = transformJsxExpression(projection, ctx2, isClientOnly);
|
|
12110
|
+
if (transformed && transformed.type === "loop") {
|
|
12111
|
+
children2 = [transformed];
|
|
12112
|
+
}
|
|
12113
|
+
}
|
|
12114
|
+
}
|
|
12115
|
+
if (method2 === "flatMap" && children2.length === 0 && !flatMapCallback && !ts11.isBlock(body2)) {
|
|
12116
|
+
flatMapCallback = buildFlatMapCallback(callback, body2, ctx2);
|
|
12117
|
+
}
|
|
12118
|
+
if (flatMapCallback) preamble = void 0;
|
|
12119
|
+
if (flatMapCallback && !isClientOnly && !(ctx2.analyzer.acceptsCallbackBody?.("flatMap") ?? false)) {
|
|
12120
|
+
ctx2.analyzer.errors.push(
|
|
12121
|
+
createError(
|
|
12122
|
+
ErrorCodes.UNSUPPORTED_JSX_PATTERN,
|
|
12123
|
+
getSourceLocation(body2, ctx2.sourceFile, ctx2.filePath),
|
|
12124
|
+
{
|
|
12125
|
+
message: "A .flatMap() callback body with statements or a nested projection cannot be lowered to a template on this backend.",
|
|
12126
|
+
suggestion: {
|
|
12127
|
+
message: "Add /* @client */ to render this loop on the client only"
|
|
12128
|
+
}
|
|
12129
|
+
}
|
|
12130
|
+
)
|
|
12131
|
+
);
|
|
12132
|
+
}
|
|
11987
12133
|
if (paramBindings) {
|
|
11988
12134
|
for (const b of paramBindings) ctx2.loopParams.delete(b.name);
|
|
11989
12135
|
} else {
|
|
@@ -11993,6 +12139,22 @@ function transformMapCall(node, ctx2, isClientOnly = false, method2 = "map") {
|
|
|
11993
12139
|
ctx2.loopDepth--;
|
|
11994
12140
|
}
|
|
11995
12141
|
if (children2.length === 0 && !flatMapCallback) {
|
|
12142
|
+
const cb = node.arguments[0];
|
|
12143
|
+
const cbBody = cb && (ts11.isArrowFunction(cb) || ts11.isFunctionExpression(cb)) ? cb.body : void 0;
|
|
12144
|
+
if (cbBody && containsJsxInExpression(cbBody) && ctx2.analyzer.errors.length === diagCountAtEntry) {
|
|
12145
|
+
ctx2.analyzer.errors.push(
|
|
12146
|
+
createError(
|
|
12147
|
+
ErrorCodes.UNSUPPORTED_JSX_PATTERN,
|
|
12148
|
+
getSourceLocation(cbBody, ctx2.sourceFile, ctx2.filePath),
|
|
12149
|
+
{
|
|
12150
|
+
message: `A .${method2}() callback that builds JSX in this shape cannot be compiled \u2014 the JSX would leak verbatim into the client bundle. Recognized bodies: a JSX element/fragment, a ternary or && / || / ?? expression, an array literal (flatMap), or a block body whose return the compiler can lower.`,
|
|
12151
|
+
suggestion: {
|
|
12152
|
+
message: "Restructure the callback to return the JSX element directly (or via a block body with a plain `return`)."
|
|
12153
|
+
}
|
|
12154
|
+
}
|
|
12155
|
+
)
|
|
12156
|
+
);
|
|
12157
|
+
}
|
|
11996
12158
|
return null;
|
|
11997
12159
|
}
|
|
11998
12160
|
if (ts11.isArrowFunction(node.arguments[0]) && children2.length > 0) {
|
|
@@ -12049,6 +12211,7 @@ function transformMapCall(node, ctx2, isClientOnly = false, method2 = "map") {
|
|
|
12049
12211
|
const hasCalls = exprHasFunctionCalls(arrayExpr);
|
|
12050
12212
|
const isDirectPropArray = method2 !== "flatMap" && isArrayExprDirectPropRef(arrayExpr, ctx2);
|
|
12051
12213
|
const isStaticArray = !isSignalOrMemoArray(array, ctx2) && !isDirectPropArray && !hasCalls && !objectIteration;
|
|
12214
|
+
const preambleRegions = preamble && !isStaticArray ? collectPreambleRegions(children2, new Set(preamble.declaredNames), ctx2) : void 0;
|
|
12052
12215
|
const nestedComponents = collectNestedComponents(children2).filter((c) => c.name !== childComponent?.name);
|
|
12053
12216
|
return {
|
|
12054
12217
|
type: "loop",
|
|
@@ -12086,6 +12249,7 @@ function transformMapCall(node, ctx2, isClientOnly = false, method2 = "map") {
|
|
|
12086
12249
|
depth,
|
|
12087
12250
|
clientOnly: isClientOnly || void 0,
|
|
12088
12251
|
preamble,
|
|
12252
|
+
preambleRegions: preambleRegions && preambleRegions.length > 0 ? preambleRegions : void 0,
|
|
12089
12253
|
paramType,
|
|
12090
12254
|
indexType,
|
|
12091
12255
|
paramBindings,
|
|
@@ -12146,6 +12310,40 @@ function buildFlatMapCallback(callback, body2, ctx2) {
|
|
|
12146
12310
|
);
|
|
12147
12311
|
return void 0;
|
|
12148
12312
|
}
|
|
12313
|
+
for (const leafIr of leafIrs) {
|
|
12314
|
+
if (leafIr.type !== "element") {
|
|
12315
|
+
const loc = "loc" in leafIr && leafIr.loc ? leafIr.loc : getSourceLocation(body2, ctx2.sourceFile, ctx2.filePath);
|
|
12316
|
+
ctx2.analyzer.errors.push(
|
|
12317
|
+
createError(
|
|
12318
|
+
ErrorCodes.UNSUPPORTED_JSX_PATTERN,
|
|
12319
|
+
loc,
|
|
12320
|
+
{
|
|
12321
|
+
message: "A JSX leaf produced by a .flatMap() callback must be a single element \u2014 a fragment or non-element root cannot ride the keyed descriptor path (each leaf hydrates and patches as one element).",
|
|
12322
|
+
suggestion: {
|
|
12323
|
+
message: "Wrap the leaf content in a single keyed element."
|
|
12324
|
+
}
|
|
12325
|
+
}
|
|
12326
|
+
)
|
|
12327
|
+
);
|
|
12328
|
+
return void 0;
|
|
12329
|
+
}
|
|
12330
|
+
if (flatMapLeafNeedsWiring(leafIr)) {
|
|
12331
|
+
const loc = "loc" in leafIr && leafIr.loc ? leafIr.loc : getSourceLocation(body2, ctx2.sourceFile, ctx2.filePath);
|
|
12332
|
+
ctx2.analyzer.errors.push(
|
|
12333
|
+
createError(
|
|
12334
|
+
ErrorCodes.UNSUPPORTED_JSX_PATTERN,
|
|
12335
|
+
loc,
|
|
12336
|
+
{
|
|
12337
|
+
message: "A JSX element produced by a .flatMap() callback cannot carry event handlers, components, nested loops, or spreads \u2014 the leaf renders as a keyed HTML string with no per-element wiring.",
|
|
12338
|
+
suggestion: {
|
|
12339
|
+
message: "Restructure so the interactive element lives in a .map() body \u2014 the descriptor path has no per-element wiring on any backend, so /* @client */ does not lift this."
|
|
12340
|
+
}
|
|
12341
|
+
}
|
|
12342
|
+
)
|
|
12343
|
+
);
|
|
12344
|
+
return void 0;
|
|
12345
|
+
}
|
|
12346
|
+
}
|
|
12149
12347
|
const pieces = reconstructAsSegments(body2, ctx2.sourceFile, ctx2.analyzer.typeExcludeRanges, leafSpans);
|
|
12150
12348
|
const segments = pieces.map((piece) => {
|
|
12151
12349
|
if ("marker" in piece) return { kind: "jsx", ir: leafIrs[piece.marker] };
|
|
@@ -12159,6 +12357,23 @@ function buildFlatMapCallback(callback, body2, ctx2) {
|
|
|
12159
12357
|
rawBody: tsxSourceText(body2.getText(ctx2.sourceFile))
|
|
12160
12358
|
};
|
|
12161
12359
|
}
|
|
12360
|
+
function flatMapLeafNeedsWiring(ir) {
|
|
12361
|
+
switch (ir.type) {
|
|
12362
|
+
case "component":
|
|
12363
|
+
case "loop":
|
|
12364
|
+
return true;
|
|
12365
|
+
case "element":
|
|
12366
|
+
if (ir.events.length > 0) return true;
|
|
12367
|
+
if (ir.attrs.some((a) => a.name.startsWith("..."))) return true;
|
|
12368
|
+
return ir.children.some(flatMapLeafNeedsWiring);
|
|
12369
|
+
case "conditional":
|
|
12370
|
+
return flatMapLeafNeedsWiring(ir.whenTrue) || (ir.whenFalse ? flatMapLeafNeedsWiring(ir.whenFalse) : false);
|
|
12371
|
+
case "fragment":
|
|
12372
|
+
return ir.children.some(flatMapLeafNeedsWiring);
|
|
12373
|
+
default:
|
|
12374
|
+
return false;
|
|
12375
|
+
}
|
|
12376
|
+
}
|
|
12162
12377
|
function preambleFragmentNeedsWiring(ir) {
|
|
12163
12378
|
switch (ir.type) {
|
|
12164
12379
|
case "component":
|
|
@@ -12202,6 +12417,39 @@ function flagArrayChildExpressions(nodes, declared) {
|
|
|
12202
12417
|
}
|
|
12203
12418
|
}
|
|
12204
12419
|
}
|
|
12420
|
+
function collectPreambleRegions(nodes, declared, ctx2) {
|
|
12421
|
+
const regions = [];
|
|
12422
|
+
const visit3 = (list) => {
|
|
12423
|
+
for (const node of list) {
|
|
12424
|
+
switch (node.type) {
|
|
12425
|
+
case "expression": {
|
|
12426
|
+
const refs = extractFreeIdentifiersFromText(node.expr);
|
|
12427
|
+
const usesPreambleLocal = [...refs].some((r2) => declared.has(r2));
|
|
12428
|
+
if (usesPreambleLocal) {
|
|
12429
|
+
if (!node.slotId) node.slotId = generateSlotId(ctx2);
|
|
12430
|
+
node.preambleRegion = true;
|
|
12431
|
+
node.reactive = true;
|
|
12432
|
+
regions.push({
|
|
12433
|
+
slotId: node.slotId,
|
|
12434
|
+
expr: node.expr,
|
|
12435
|
+
joinArrayChild: node.joinArrayChild || void 0
|
|
12436
|
+
});
|
|
12437
|
+
}
|
|
12438
|
+
break;
|
|
12439
|
+
}
|
|
12440
|
+
case "element":
|
|
12441
|
+
case "fragment":
|
|
12442
|
+
visit3(node.children);
|
|
12443
|
+
break;
|
|
12444
|
+
case "conditional":
|
|
12445
|
+
visit3([node.whenTrue, ...node.whenFalse ? [node.whenFalse] : []]);
|
|
12446
|
+
break;
|
|
12447
|
+
}
|
|
12448
|
+
}
|
|
12449
|
+
};
|
|
12450
|
+
visit3(nodes);
|
|
12451
|
+
return regions;
|
|
12452
|
+
}
|
|
12205
12453
|
function collectBindingNames(name2, out) {
|
|
12206
12454
|
if (ts11.isIdentifier(name2)) {
|
|
12207
12455
|
out.add(name2.text);
|
|
@@ -13570,6 +13818,7 @@ function collectLoopChildReactiveTexts(node, ctx2, loopParam, loopParamBindings,
|
|
|
13570
13818
|
...stopAt("loop", "async", "ifStatement"),
|
|
13571
13819
|
expression: ({ node: n, scope: insideConditional }) => {
|
|
13572
13820
|
if (!n.slotId) return;
|
|
13821
|
+
if (n.preambleRegion) return;
|
|
13573
13822
|
const originFreeIds = freeIdsFromRefs(n.origin?.freeRefs);
|
|
13574
13823
|
const expanded = expandConstantForReactivity(n.expr, ctx2, originFreeIds);
|
|
13575
13824
|
const reactive = classifyReactivity(expanded.expr, ctx2, loopParam, loopParamBindings, expanded.freeIds).kind !== "none" || decideWrapFromAstFlags(n).wrap;
|
|
@@ -14078,7 +14327,11 @@ function collectElements(node, ctx2, siblingOffsets, insideConditional = false)
|
|
|
14078
14327
|
},
|
|
14079
14328
|
expression: ({ node: ex, scope: inCond }) => {
|
|
14080
14329
|
if (ex.clientOnly && ex.slotId) {
|
|
14081
|
-
ctx2.clientOnlyElements.push({
|
|
14330
|
+
ctx2.clientOnlyElements.push({
|
|
14331
|
+
slotId: ex.slotId,
|
|
14332
|
+
expression: ex.expr,
|
|
14333
|
+
elidedPath: ex.markerless ? ex.elidedPath : void 0
|
|
14334
|
+
});
|
|
14082
14335
|
return;
|
|
14083
14336
|
}
|
|
14084
14337
|
if (!ex.slotId || inCond) return;
|
|
@@ -14102,10 +14355,13 @@ function collectElements(node, ctx2, siblingOffsets, insideConditional = false)
|
|
|
14102
14355
|
},
|
|
14103
14356
|
loop: ({ node: l, scope: inCond }) => {
|
|
14104
14357
|
if (!l.slotId || inCond) return;
|
|
14358
|
+
const projectionInner = l.method === "flatMap" && l.children.length === 1 && l.children[0].type === "loop" ? l.children[0] : void 0;
|
|
14105
14359
|
const childHandlers = [];
|
|
14106
|
-
const bindings = collectLoopChildBindings(l.children, ctx2, siblingOffsets, l.param, l.paramBindings);
|
|
14107
|
-
|
|
14108
|
-
|
|
14360
|
+
const bindings = projectionInner ? emptyLoopChildBindings() : collectLoopChildBindings(l.children, ctx2, siblingOffsets, l.param, l.paramBindings);
|
|
14361
|
+
if (!projectionInner) {
|
|
14362
|
+
for (const child of l.children) {
|
|
14363
|
+
childHandlers.push(...collectEventHandlersFromIR(child));
|
|
14364
|
+
}
|
|
14109
14365
|
}
|
|
14110
14366
|
if (l.childComponent) {
|
|
14111
14367
|
for (const prop of l.childComponent.props) {
|
|
@@ -14115,7 +14371,7 @@ function collectElements(node, ctx2, siblingOffsets, insideConditional = false)
|
|
|
14115
14371
|
}
|
|
14116
14372
|
}
|
|
14117
14373
|
}
|
|
14118
|
-
const { useElementReconciliation, innerLoops } = decideLoopRendering(l, siblingOffsets, ctx2);
|
|
14374
|
+
const { useElementReconciliation, innerLoops } = projectionInner ? { useElementReconciliation: false, innerLoops: void 0 } : decideLoopRendering(l, siblingOffsets, ctx2);
|
|
14119
14375
|
let template = "";
|
|
14120
14376
|
let staticItemTemplate;
|
|
14121
14377
|
let skeletonTemplate;
|
|
@@ -14133,7 +14389,7 @@ function collectElements(node, ctx2, siblingOffsets, insideConditional = false)
|
|
|
14133
14389
|
true
|
|
14134
14390
|
);
|
|
14135
14391
|
}
|
|
14136
|
-
} else if (l.children[0]) {
|
|
14392
|
+
} else if (l.children[0] && !projectionInner) {
|
|
14137
14393
|
const loopParamSpec = [{ param: l.param, bindings: l.paramBindings }];
|
|
14138
14394
|
template = useElementReconciliation ? irToPlaceholderTemplate(l.children[0], buildRestSpreadNames(ctx2), 0, loopParamSpec) : irToHtmlTemplate(l.children[0], buildRestSpreadNames(ctx2), 0, loopParamSpec);
|
|
14139
14395
|
if (l.isStaticArray) {
|
|
@@ -14185,7 +14441,17 @@ function collectElements(node, ctx2, siblingOffsets, insideConditional = false)
|
|
|
14185
14441
|
raw: l.sortComparator.raw
|
|
14186
14442
|
} : void 0,
|
|
14187
14443
|
chainOrder: l.chainOrder,
|
|
14188
|
-
preamble: l.preamble
|
|
14444
|
+
preamble: l.preamble,
|
|
14445
|
+
preambleRegions: l.preambleRegions,
|
|
14446
|
+
flatMapClient: projectionInner ? {
|
|
14447
|
+
params: l.index ? `(${l.param}, ${l.index})` : `(${l.param})`,
|
|
14448
|
+
body: renderFlatMapProjectionClientBody(projectionInner, buildRestSpreadNames(ctx2)),
|
|
14449
|
+
keyed: projectionInner.key !== null
|
|
14450
|
+
} : l.flatMapCallback ? {
|
|
14451
|
+
params: l.flatMapCallback.params,
|
|
14452
|
+
body: renderFlatMapClientBody(l.flatMapCallback, buildRestSpreadNames(ctx2)),
|
|
14453
|
+
keyed: flatMapCallbackHasKeyedLeaf(l.flatMapCallback)
|
|
14454
|
+
} : void 0
|
|
14189
14455
|
});
|
|
14190
14456
|
},
|
|
14191
14457
|
component: ({ node: c, descend, descendJsxChildren }) => {
|
|
@@ -14340,15 +14606,18 @@ function collectBranchLoops(node, ctx2, siblingOffsets) {
|
|
|
14340
14606
|
loop: ({ node: n, scope: parentSlotId }) => {
|
|
14341
14607
|
const containerSlot = parentSlotId ?? n.slotId;
|
|
14342
14608
|
if (!containerSlot) return;
|
|
14343
|
-
const
|
|
14609
|
+
const projectionInner = n.method === "flatMap" && n.children.length === 1 && n.children[0].type === "loop" ? n.children[0] : void 0;
|
|
14610
|
+
const { useElementReconciliation, innerLoops: innerLoopsCollected } = projectionInner ? { useElementReconciliation: false, innerLoops: void 0 } : decideLoopRendering(n, siblingOffsets, void 0);
|
|
14344
14611
|
let childTemplate;
|
|
14345
14612
|
const branchLoopParamSpec = [{ param: n.param, bindings: n.paramBindings }];
|
|
14346
|
-
if (
|
|
14613
|
+
if (projectionInner) {
|
|
14614
|
+
childTemplate = "";
|
|
14615
|
+
} else if (useElementReconciliation && n.children[0]) {
|
|
14347
14616
|
childTemplate = irToPlaceholderTemplate(n.children[0], restNames, 0, branchLoopParamSpec);
|
|
14348
14617
|
} else {
|
|
14349
14618
|
childTemplate = n.children.map((c) => irToHtmlTemplate(c, void 0, 0, branchLoopParamSpec)).join("");
|
|
14350
14619
|
}
|
|
14351
|
-
const branchBindings = ctx2 ? collectLoopChildBindings(n.children, ctx2, siblingOffsets, n.param, n.paramBindings) : emptyLoopChildBindings();
|
|
14620
|
+
const branchBindings = ctx2 && !projectionInner ? collectLoopChildBindings(n.children, ctx2, siblingOffsets, n.param, n.paramBindings) : emptyLoopChildBindings();
|
|
14352
14621
|
loops.push({
|
|
14353
14622
|
kind: "branch",
|
|
14354
14623
|
array: n.array,
|
|
@@ -14365,6 +14634,7 @@ function collectBranchLoops(node, ctx2, siblingOffsets) {
|
|
|
14365
14634
|
template: childTemplate,
|
|
14366
14635
|
containerSlotId: containerSlot,
|
|
14367
14636
|
preamble: n.preamble,
|
|
14637
|
+
preambleRegions: n.preambleRegions,
|
|
14368
14638
|
nestedComponents: useElementReconciliation ? n.nestedComponents : void 0,
|
|
14369
14639
|
bindings: branchBindings,
|
|
14370
14640
|
innerLoops: useElementReconciliation ? innerLoopsCollected : void 0,
|
|
@@ -14378,7 +14648,16 @@ function collectBranchLoops(node, ctx2, siblingOffsets) {
|
|
|
14378
14648
|
paramB: n.sortComparator.paramB,
|
|
14379
14649
|
raw: n.sortComparator.raw
|
|
14380
14650
|
} : void 0,
|
|
14381
|
-
chainOrder: n.chainOrder
|
|
14651
|
+
chainOrder: n.chainOrder,
|
|
14652
|
+
flatMapClient: projectionInner ? {
|
|
14653
|
+
params: n.index ? `(${n.param}, ${n.index})` : `(${n.param})`,
|
|
14654
|
+
body: renderFlatMapProjectionClientBody(projectionInner, restNames),
|
|
14655
|
+
keyed: projectionInner.key !== null
|
|
14656
|
+
} : n.flatMapCallback ? {
|
|
14657
|
+
params: n.flatMapCallback.params,
|
|
14658
|
+
body: renderFlatMapClientBody(n.flatMapCallback, restNames),
|
|
14659
|
+
keyed: flatMapCallbackHasKeyedLeaf(n.flatMapCallback)
|
|
14660
|
+
} : void 0
|
|
14382
14661
|
});
|
|
14383
14662
|
}
|
|
14384
14663
|
});
|
|
@@ -14774,6 +15053,12 @@ function buildReferencesGraph(ctx2, irRoot) {
|
|
|
14774
15053
|
if (l.filterPredicate) addExprEdges(ROOT_SOURCE, l.filterPredicate.raw, "template-closure");
|
|
14775
15054
|
if (l.sortComparator) addExprEdges(ROOT_SOURCE, l.sortComparator.raw, "template-closure");
|
|
14776
15055
|
if (l.preamble) addExprEdges(ROOT_SOURCE, preambleAnalysisText(l.preamble), "template-closure");
|
|
15056
|
+
if (l.flatMapCallback) {
|
|
15057
|
+
addExprEdges(ROOT_SOURCE, preambleAnalysisText(l.flatMapCallback), "template-closure");
|
|
15058
|
+
for (const seg of l.flatMapCallback.segments) {
|
|
15059
|
+
if (seg.kind === "jsx") walkIR(seg.ir, null, visitor);
|
|
15060
|
+
}
|
|
15061
|
+
}
|
|
14777
15062
|
descend();
|
|
14778
15063
|
if (l.childComponent) walkChildComponent(l.childComponent);
|
|
14779
15064
|
if (l.nestedComponents) {
|
|
@@ -15050,11 +15335,11 @@ var init_imports = __esm({
|
|
|
15050
15335
|
"onMount",
|
|
15051
15336
|
"hydrate",
|
|
15052
15337
|
"insert",
|
|
15053
|
-
"reconcileElements",
|
|
15054
15338
|
"getLoopChildren",
|
|
15055
15339
|
"getLoopNodes",
|
|
15056
15340
|
"mapArray",
|
|
15057
15341
|
"mapArrayAnchored",
|
|
15342
|
+
"patchLeaf",
|
|
15058
15343
|
"createDisposableEffect",
|
|
15059
15344
|
"createComponent",
|
|
15060
15345
|
"renderChild",
|
|
@@ -15062,7 +15347,6 @@ var init_imports = __esm({
|
|
|
15062
15347
|
"registerTemplate",
|
|
15063
15348
|
"initChild",
|
|
15064
15349
|
"upsertChild",
|
|
15065
|
-
"updateClientMarker",
|
|
15066
15350
|
"createPortal",
|
|
15067
15351
|
"provideContext",
|
|
15068
15352
|
"createContext",
|
|
@@ -15074,6 +15358,7 @@ var init_imports = __esm({
|
|
|
15074
15358
|
"styleToCss",
|
|
15075
15359
|
"escapeAttr",
|
|
15076
15360
|
"escapeText",
|
|
15361
|
+
"escapeTextOrNode",
|
|
15077
15362
|
"qsa",
|
|
15078
15363
|
"qsaItem",
|
|
15079
15364
|
"qsaChildScope",
|
|
@@ -15082,7 +15367,11 @@ var init_imports = __esm({
|
|
|
15082
15367
|
"__slot",
|
|
15083
15368
|
"__bfSlot",
|
|
15084
15369
|
"__bfText",
|
|
15085
|
-
|
|
15370
|
+
// Claim-plan interpreter (slot unification A2/A3, spec/slot-unification.md)
|
|
15371
|
+
// — the "one claim mechanism" that replaced `patchSlotRange` and
|
|
15372
|
+
// `updateClientMarker` (both deleted) as the content-slot update door.
|
|
15373
|
+
"claimSlots",
|
|
15374
|
+
"lazySlots",
|
|
15086
15375
|
// Profile mode (#1690, SR3) — turn-boundary markers around event handlers.
|
|
15087
15376
|
"beginTurn",
|
|
15088
15377
|
"endTurn",
|
|
@@ -17006,6 +17295,14 @@ function destructureLoopParam(param, paramBindings) {
|
|
|
17006
17295
|
}
|
|
17007
17296
|
return { head: param, unwrap: "" };
|
|
17008
17297
|
}
|
|
17298
|
+
function buildPreambleRegionPlans(regions, loopParam, loopParamBindings) {
|
|
17299
|
+
if (!regions || regions.length === 0) return [];
|
|
17300
|
+
return regions.map((r2) => {
|
|
17301
|
+
const wrapped = wrapLoopParamAsAccessor(r2.expr, loopParam, loopParamBindings);
|
|
17302
|
+
const valueExpr = r2.joinArrayChild ? `Array.isArray(${wrapped}) ? ${wrapped}.join('') : (${wrapped} ?? '')` : `escapeText(${wrapped})`;
|
|
17303
|
+
return { slotId: r2.slotId, valueExpr };
|
|
17304
|
+
});
|
|
17305
|
+
}
|
|
17009
17306
|
function buildComponentPropsExpr2(comp, loopParam, loopParamBindings) {
|
|
17010
17307
|
const wrap = loopParam ? (expr) => wrapLoopParamAsAccessor(expr, loopParam, loopParamBindings) : (expr) => expr;
|
|
17011
17308
|
const entries2 = comp.props.map((p) => {
|
|
@@ -18104,9 +18401,16 @@ function buildDynamicLoopDelegationPlan(elem, profileComponentName) {
|
|
|
18104
18401
|
paramBindings: elem.paramBindings,
|
|
18105
18402
|
key: elem.key,
|
|
18106
18403
|
index: elem.index,
|
|
18404
|
+
// No loopParams spec here (unlike the row-render context) — in the
|
|
18405
|
+
// delegated handler `elem.param` is bound to the plain `.find()`/
|
|
18406
|
+
// indexed result, not a signal accessor, so leaf refs must stay in
|
|
18407
|
+
// their literal (`t.name`) form. Passing a loopParams spec here was
|
|
18408
|
+
// BUG-3: it rewrote leaf refs to accessor-call form (`t().name`),
|
|
18409
|
+
// which throws since `t` is a plain object in this scope.
|
|
18107
18410
|
mapPreamble: elem.preamble ? renderPreamble(elem.preamble, {
|
|
18108
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, void 0, 1,
|
|
18109
|
-
}) : null
|
|
18411
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, void 0, 1, void 0, void 0, true)
|
|
18412
|
+
}) : null,
|
|
18413
|
+
mapPreambleDeclaredNames: elem.preamble?.declaredNames ?? []
|
|
18110
18414
|
})
|
|
18111
18415
|
};
|
|
18112
18416
|
}
|
|
@@ -18123,9 +18427,12 @@ function buildBranchLoopDelegationPlan(loop, cv, profileComponentName) {
|
|
|
18123
18427
|
paramBindings: loop.paramBindings,
|
|
18124
18428
|
key: loop.key,
|
|
18125
18429
|
index: loop.index,
|
|
18430
|
+
// See note in `buildDynamicLoopDelegationPlan` above (BUG-3): no
|
|
18431
|
+
// loopParams spec — leaf refs must stay in plain-object form here.
|
|
18126
18432
|
mapPreamble: loop.preamble ? renderPreamble(loop.preamble, {
|
|
18127
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, void 0, 1,
|
|
18128
|
-
}) : null
|
|
18433
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, void 0, 1, void 0, void 0, true)
|
|
18434
|
+
}) : null,
|
|
18435
|
+
mapPreambleDeclaredNames: loop.preamble?.declaredNames ?? []
|
|
18129
18436
|
})
|
|
18130
18437
|
};
|
|
18131
18438
|
}
|
|
@@ -18142,9 +18449,12 @@ function buildStaticArrayDelegationPlan(elem, profileComponentName) {
|
|
|
18142
18449
|
// array too (#1434).
|
|
18143
18450
|
arrayExpr: buildChainedArrayExpr(elem),
|
|
18144
18451
|
param: elem.param,
|
|
18452
|
+
// See note in `buildDynamicLoopDelegationPlan` above (BUG-3): no
|
|
18453
|
+
// loopParams spec — leaf refs must stay in plain-object form here.
|
|
18145
18454
|
mapPreamble: elem.preamble ? renderPreamble(elem.preamble, {
|
|
18146
|
-
renderLeaf: (ir) => irToHtmlTemplate(ir, void 0, 1,
|
|
18455
|
+
renderLeaf: (ir) => irToHtmlTemplate(ir, void 0, 1, void 0, void 0, true)
|
|
18147
18456
|
}) : null,
|
|
18457
|
+
mapPreambleDeclaredNames: elem.preamble?.declaredNames ?? [],
|
|
18148
18458
|
offset: elem.offset ?? null,
|
|
18149
18459
|
indexParam: elem.index ?? null
|
|
18150
18460
|
}
|
|
@@ -18161,6 +18471,7 @@ function buildKeyedOrIndexLookup(args2) {
|
|
|
18161
18471
|
paramBindings: args2.paramBindings,
|
|
18162
18472
|
keyWithItem,
|
|
18163
18473
|
mapPreamble: args2.mapPreamble,
|
|
18474
|
+
mapPreambleDeclaredNames: args2.mapPreambleDeclaredNames,
|
|
18164
18475
|
hasBindings,
|
|
18165
18476
|
indexParam: args2.index
|
|
18166
18477
|
};
|
|
@@ -18170,6 +18481,7 @@ function buildKeyedOrIndexLookup(args2) {
|
|
|
18170
18481
|
arrayExpr: args2.array,
|
|
18171
18482
|
param: args2.param,
|
|
18172
18483
|
mapPreamble: args2.mapPreamble,
|
|
18484
|
+
mapPreambleDeclaredNames: args2.mapPreambleDeclaredNames,
|
|
18173
18485
|
hasBindings,
|
|
18174
18486
|
indexParam: args2.index
|
|
18175
18487
|
};
|
|
@@ -18198,14 +18510,16 @@ function buildBranchLoopPlan(loop, profileComponentName) {
|
|
|
18198
18510
|
}
|
|
18199
18511
|
const { head: paramHead, unwrap: paramUnwrap } = destructureLoopParam(loop.param, loop.paramBindings);
|
|
18200
18512
|
const hasReactiveEffects = loop.bindings.reactiveAttrs.length > 0 || loop.bindings.reactiveTexts.length > 0 || loop.bindings.conditionals.length > 0;
|
|
18513
|
+
const fm = loop.flatMapClient;
|
|
18201
18514
|
const plan = {
|
|
18202
18515
|
kind: "plain",
|
|
18203
18516
|
rowConstruction: "string-template",
|
|
18204
18517
|
containerSlotId,
|
|
18205
18518
|
containerVar,
|
|
18206
18519
|
markerId: loop.markerId,
|
|
18207
|
-
|
|
18208
|
-
|
|
18520
|
+
flatMapLeafItem: fm ? true : void 0,
|
|
18521
|
+
arrayExpr: fm ? `(${buildChainedArrayExpr(loop)}).flatMap(${fm.params} => ${fm.body})` : buildChainedArrayExpr(loop),
|
|
18522
|
+
keyFn: fm ? fm.keyed ? "(__bfD, __bfI) => String(__bfD.k ?? __bfI)" : "null" : loopKeyFn(loop),
|
|
18209
18523
|
paramHead,
|
|
18210
18524
|
paramUnwrap,
|
|
18211
18525
|
indexParam: loop.index || "__idx",
|
|
@@ -18226,6 +18540,7 @@ function buildBranchLoopPlan(loop, profileComponentName) {
|
|
|
18226
18540
|
}) : null,
|
|
18227
18541
|
eventDelegation: buildBranchLoopDelegationPlan(loop, cv, profileComponentName),
|
|
18228
18542
|
childRefs: buildChildRefBindings(loop.bindings.refs, loop.param, loop.paramBindings),
|
|
18543
|
+
preambleRegions: buildPreambleRegionPlans(loop.preambleRegions, loop.param, loop.paramBindings),
|
|
18229
18544
|
bodyIsMultiRoot: loop.bodyIsMultiRoot ?? false,
|
|
18230
18545
|
profileLoopId: profileComponentName ? `${profileComponentName}#binding:${containerSlotId}` : void 0
|
|
18231
18546
|
};
|
|
@@ -18312,6 +18627,25 @@ var init_build_insert = __esm({
|
|
|
18312
18627
|
}
|
|
18313
18628
|
});
|
|
18314
18629
|
|
|
18630
|
+
// ../jsx/src/ir-to-client-js/control-flow/stringify/claim-plan.ts
|
|
18631
|
+
function slotSpecLiteral(slot) {
|
|
18632
|
+
const pathSrc = slot.pathExpr ?? `[${slot.path.join(", ")}]`;
|
|
18633
|
+
const markerlessSrc = slot.markerless ? ", markerless: true" : "";
|
|
18634
|
+
return `{ id: '${slot.id}', kind: '${slot.kind}', path: ${pathSrc}${markerlessSrc} }`;
|
|
18635
|
+
}
|
|
18636
|
+
function claimPlanLiteral(slots) {
|
|
18637
|
+
return `[${slots.map(slotSpecLiteral).join(", ")}]`;
|
|
18638
|
+
}
|
|
18639
|
+
function claimWriterVarName(slots, sanitize) {
|
|
18640
|
+
const first = slots[0]?.id ?? "0";
|
|
18641
|
+
return `__bfw_${sanitize(first)}`;
|
|
18642
|
+
}
|
|
18643
|
+
var init_claim_plan = __esm({
|
|
18644
|
+
"../jsx/src/ir-to-client-js/control-flow/stringify/claim-plan.ts"() {
|
|
18645
|
+
"use strict";
|
|
18646
|
+
}
|
|
18647
|
+
});
|
|
18648
|
+
|
|
18315
18649
|
// ../jsx/src/ir-to-client-js/emit-reactive.ts
|
|
18316
18650
|
import ts14 from "typescript";
|
|
18317
18651
|
function bindingIdArg(ctx2, slotId) {
|
|
@@ -18490,17 +18824,18 @@ function emitDynamicTextUpdates(lines, ctx2) {
|
|
|
18490
18824
|
const conditionalElems = elems.filter((e) => e.insideConditional);
|
|
18491
18825
|
const normalElems = elems.filter((e) => !e.insideConditional);
|
|
18492
18826
|
if (normalElems.length > 0 || conditionalElems.length > 0) {
|
|
18493
|
-
for (const elem of normalElems) {
|
|
18494
|
-
const v = varSlotId(elem.slotId);
|
|
18495
|
-
lines.push(` let __anchor_${v} = _${v}`);
|
|
18496
|
-
}
|
|
18497
18827
|
const __textSlot = (normalElems[0] ?? conditionalElems[0])?.slotId;
|
|
18828
|
+
let writer = "";
|
|
18829
|
+
if (normalElems.length > 0) {
|
|
18830
|
+
const slots = normalElems.map((elem) => ({ id: elem.slotId, kind: "markup", path: [] }));
|
|
18831
|
+
writer = claimWriterVarName(slots, varSlotId);
|
|
18832
|
+
lines.push(` const ${writer} = lazySlots(__scope, ${claimPlanLiteral(slots)})`);
|
|
18833
|
+
}
|
|
18498
18834
|
lines.push(` createEffect(() => {`);
|
|
18499
18835
|
if (normalElems.length > 0) {
|
|
18500
18836
|
lines.push(` const __val = ${expr}`);
|
|
18501
18837
|
for (const elem of normalElems) {
|
|
18502
|
-
|
|
18503
|
-
lines.push(` __anchor_${v} = __bfText(__anchor_${v}, __val)`);
|
|
18838
|
+
lines.push(` ${writer}('${elem.slotId}', escapeTextOrNode(__val))`);
|
|
18504
18839
|
}
|
|
18505
18840
|
for (const elem of conditionalElems) {
|
|
18506
18841
|
const v = varSlotId(elem.slotId);
|
|
@@ -18523,10 +18858,13 @@ function emitDynamicTextUpdates(lines, ctx2) {
|
|
|
18523
18858
|
}
|
|
18524
18859
|
function emitClientOnlyExpressions(lines, ctx2) {
|
|
18525
18860
|
for (const elem of ctx2.clientOnlyElements) {
|
|
18861
|
+
const slots = elem.elidedPath ? [{ id: elem.slotId, kind: "text", path: elem.elidedPath, markerless: true }] : [{ id: elem.slotId, kind: "text", path: [] }];
|
|
18862
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
18526
18863
|
lines.push(` // @client: ${elem.slotId}`);
|
|
18864
|
+
lines.push(` { const ${writer} = lazySlots(__scope, ${claimPlanLiteral(slots)})`);
|
|
18527
18865
|
lines.push(` createEffect(() => {`);
|
|
18528
|
-
lines.push(`
|
|
18529
|
-
lines.push(` }${bindingIdArg(ctx2, elem.slotId)})`);
|
|
18866
|
+
lines.push(` ${writer}('${elem.slotId}', ${elem.expression})`);
|
|
18867
|
+
lines.push(` }${bindingIdArg(ctx2, elem.slotId)}) }`);
|
|
18530
18868
|
lines.push("");
|
|
18531
18869
|
}
|
|
18532
18870
|
}
|
|
@@ -18634,6 +18972,7 @@ var init_emit_reactive = __esm({
|
|
|
18634
18972
|
"use strict";
|
|
18635
18973
|
init_html_constants();
|
|
18636
18974
|
init_utils();
|
|
18975
|
+
init_claim_plan();
|
|
18637
18976
|
init_html_template();
|
|
18638
18977
|
init_date_lowering();
|
|
18639
18978
|
init_to_locale_date_lowering();
|
|
@@ -18703,13 +19042,18 @@ function stringifyBranchInnerLoops(lines, plan, indent, pc) {
|
|
|
18703
19042
|
inner.outerLoopParamBindings
|
|
18704
19043
|
);
|
|
18705
19044
|
}
|
|
18706
|
-
|
|
19045
|
+
const conditionalTexts = inner.reactiveTexts.filter((t) => t.insideConditional);
|
|
19046
|
+
const plainTexts = inner.reactiveTexts.filter((t) => !t.insideConditional);
|
|
19047
|
+
for (const text of conditionalTexts) {
|
|
18707
19048
|
const bf = profileBindingId(pc, text.slotId);
|
|
18708
|
-
|
|
18709
|
-
|
|
18710
|
-
|
|
18711
|
-
|
|
18712
|
-
|
|
19049
|
+
lines.push(`${indent} createEffect(() => { claimSlots(__bel${uid}, [{ id: '${text.slotId}', kind: 'text', path: [] }]).write('${text.slotId}', String(${text.wrappedExpression})) }${bf})`);
|
|
19050
|
+
}
|
|
19051
|
+
if (plainTexts.length > 0) {
|
|
19052
|
+
const slots = plainTexts.map((t) => ({ id: t.slotId, kind: "text", path: [] }));
|
|
19053
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
19054
|
+
lines.push(`${indent} const ${writer} = lazySlots(__bel${uid}, ${claimPlanLiteral(slots)})`);
|
|
19055
|
+
for (const text of plainTexts) {
|
|
19056
|
+
lines.push(`${indent} createEffect(() => { ${writer}('${text.slotId}', String(${text.wrappedExpression})) }${profileBindingId(pc, text.slotId)})`);
|
|
18713
19057
|
}
|
|
18714
19058
|
}
|
|
18715
19059
|
if (inner.nestedConditionals.length > 0) {
|
|
@@ -18751,10 +19095,13 @@ function stringifyLoopChildArm(lines, arm, armIndent, pc) {
|
|
|
18751
19095
|
stringifyLoopChildConditional(lines, cond, `${armIndent} `, pc);
|
|
18752
19096
|
lines.push(`${armIndent}}))`);
|
|
18753
19097
|
}
|
|
18754
|
-
|
|
18755
|
-
const
|
|
18756
|
-
|
|
18757
|
-
lines.push(`${armIndent}
|
|
19098
|
+
if (arm.texts.length > 0) {
|
|
19099
|
+
const slots = arm.texts.map((t) => ({ id: t.slotId, kind: "markup", path: [] }));
|
|
19100
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
19101
|
+
lines.push(`${armIndent}const ${writer} = lazySlots(__branchScope, ${claimPlanLiteral(slots)})`);
|
|
19102
|
+
for (const text of arm.texts) {
|
|
19103
|
+
lines.push(`${armIndent}__disposers.push(createDisposableEffect(() => { ${writer}('${text.slotId}', escapeTextOrNode(${text.wrappedExpression})) }${profileBindingId(pc, text.slotId)}))`);
|
|
19104
|
+
}
|
|
18758
19105
|
}
|
|
18759
19106
|
lines.push(`${armIndent}return () => __disposers.forEach(d => d())`);
|
|
18760
19107
|
}
|
|
@@ -18767,19 +19114,45 @@ var init_loop_child_arm = __esm({
|
|
|
18767
19114
|
init_template_parse();
|
|
18768
19115
|
init_event_listener();
|
|
18769
19116
|
init_component_scope();
|
|
19117
|
+
init_claim_plan();
|
|
18770
19118
|
}
|
|
18771
19119
|
});
|
|
18772
19120
|
|
|
18773
19121
|
// ../jsx/src/ir-to-client-js/control-flow/stringify/reactive-effects.ts
|
|
18774
19122
|
function stringifyReactiveEffects(lines, plan, opts) {
|
|
18775
|
-
const { indent, elVar, bodyIsMultiRoot, elementIndexBySlot,
|
|
19123
|
+
const { indent, elVar, bodyIsMultiRoot, elementIndexBySlot, textClaimPathExprs, preambleRegions = [], mapPreambleWrapped } = opts;
|
|
18776
19124
|
const lookup = bodyIsMultiRoot ? "qsaItem" : "qsa";
|
|
18777
|
-
const pc = plan
|
|
19125
|
+
const pc = plan?.profileComponentName;
|
|
18778
19126
|
const bindingBfId = (slotId) => profileBindingId(pc, slotId);
|
|
18779
|
-
|
|
19127
|
+
const attrSlots = plan?.attrSlots ?? [];
|
|
19128
|
+
const outerTexts = plan?.outerTexts ?? [];
|
|
19129
|
+
const conditionals = plan?.conditionals ?? [];
|
|
19130
|
+
if (pc) {
|
|
19131
|
+
emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId);
|
|
19132
|
+
emitOuterTexts(lines, indent, elVar, outerTexts, bindingBfId, textClaimPathExprs);
|
|
19133
|
+
emitPreambleRegionsEffect(lines, indent, elVar, preambleRegions, mapPreambleWrapped);
|
|
19134
|
+
} else {
|
|
19135
|
+
emitConsolidatedRowEffect(
|
|
19136
|
+
lines,
|
|
19137
|
+
indent,
|
|
19138
|
+
elVar,
|
|
19139
|
+
lookup,
|
|
19140
|
+
attrSlots,
|
|
19141
|
+
outerTexts,
|
|
19142
|
+
elementIndexBySlot,
|
|
19143
|
+
textClaimPathExprs,
|
|
19144
|
+
preambleRegions,
|
|
19145
|
+
mapPreambleWrapped
|
|
19146
|
+
);
|
|
19147
|
+
}
|
|
19148
|
+
for (const cond of conditionals) {
|
|
19149
|
+
emitOuterConditional(lines, indent, elVar, cond, pc);
|
|
19150
|
+
}
|
|
19151
|
+
}
|
|
19152
|
+
function emitAttrSlotsGranular(lines, indent, elVar, lookup, attrSlots, elementIndexBySlot, bindingBfId) {
|
|
19153
|
+
for (const slot of attrSlots) {
|
|
18780
19154
|
const varName = `__ra_${varSlotId(slot.slotId)}`;
|
|
18781
|
-
const
|
|
18782
|
-
const lookupExpr = pIdx !== void 0 ? `__p ? __p[${pIdx}] : ${lookup}(${elVar}, '[bf="${slot.slotId}"]')` : `${lookup}(${elVar}, '[bf="${slot.slotId}"]')`;
|
|
19155
|
+
const lookupExpr = attrLookupExpr(slot.slotId, varName, elVar, lookup, elementIndexBySlot);
|
|
18783
19156
|
lines.push(`${indent}{ const ${varName} = ${lookupExpr}`);
|
|
18784
19157
|
lines.push(`${indent}if (${varName}) {`);
|
|
18785
19158
|
for (const attr of slot.attrs) {
|
|
@@ -18791,21 +19164,79 @@ function stringifyReactiveEffects(lines, plan, opts) {
|
|
|
18791
19164
|
}
|
|
18792
19165
|
lines.push(`${indent}} }`);
|
|
18793
19166
|
}
|
|
18794
|
-
|
|
18795
|
-
|
|
19167
|
+
}
|
|
19168
|
+
function emitPreambleRegionsEffect(lines, indent, elVar, preambleRegions, mapPreambleWrapped) {
|
|
19169
|
+
if (preambleRegions.length === 0) return;
|
|
19170
|
+
const slots = preambleRegions.map((r2) => ({ id: r2.slotId, kind: "markup", path: [] }));
|
|
19171
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
19172
|
+
lines.push(`${indent}const ${writer} = lazySlots(${elVar}, ${claimPlanLiteral(slots)})`);
|
|
19173
|
+
lines.push(`${indent}createEffect(() => {`);
|
|
19174
|
+
if (mapPreambleWrapped) lines.push(`${indent} ${mapPreambleWrapped}`);
|
|
19175
|
+
for (const region of preambleRegions) {
|
|
19176
|
+
lines.push(`${indent} ${writer}('${region.slotId}', ${region.valueExpr})`);
|
|
18796
19177
|
}
|
|
18797
|
-
|
|
18798
|
-
|
|
19178
|
+
lines.push(`${indent}})`);
|
|
19179
|
+
}
|
|
19180
|
+
function attrLookupExpr(slotId, varName, elVar, lookup, elementIndexBySlot) {
|
|
19181
|
+
const pIdx = elementIndexBySlot?.get(slotId);
|
|
19182
|
+
return pIdx !== void 0 ? `__p ? __p[${pIdx}] : ${lookup}(${elVar}, '[bf="${slotId}"]')` : `${lookup}(${elVar}, '[bf="${slotId}"]')`;
|
|
19183
|
+
}
|
|
19184
|
+
function emitConsolidatedRowEffect(lines, indent, elVar, lookup, attrSlots, outerTexts, elementIndexBySlot, textClaimPathExprs, preambleRegions, mapPreambleWrapped) {
|
|
19185
|
+
if (attrSlots.length === 0 && outerTexts.length === 0 && preambleRegions.length === 0) return;
|
|
19186
|
+
for (const slot of attrSlots) {
|
|
19187
|
+
const varName = `__ra_${varSlotId(slot.slotId)}`;
|
|
19188
|
+
lines.push(`${indent}const ${varName} = ${attrLookupExpr(slot.slotId, varName, elVar, lookup, elementIndexBySlot)}`);
|
|
19189
|
+
}
|
|
19190
|
+
const claimSlots = [
|
|
19191
|
+
...outerTexts.map((t) => ({ id: t.slotId, kind: "text", path: [], pathExpr: textClaimPathExprs?.get(t.slotId) })),
|
|
19192
|
+
...preambleRegions.map((r2) => ({ id: r2.slotId, kind: "markup", path: [] }))
|
|
19193
|
+
];
|
|
19194
|
+
const writer = claimSlots.length > 0 ? claimWriterVarName(claimSlots, varSlotId) : null;
|
|
19195
|
+
if (writer) {
|
|
19196
|
+
lines.push(`${indent}const ${writer} = lazySlots(${elVar}, ${claimPlanLiteral(claimSlots)})`);
|
|
19197
|
+
}
|
|
19198
|
+
if (attrSlots.length === 0 && preambleRegions.length === 0 && outerTexts.length === 1) {
|
|
19199
|
+
const text = outerTexts[0];
|
|
19200
|
+
lines.push(`${indent}createEffect(() => { ${writer}('${text.slotId}', String(${text.wrappedExpression})) })`);
|
|
19201
|
+
return;
|
|
19202
|
+
}
|
|
19203
|
+
lines.push(`${indent}createEffect(() => {`);
|
|
19204
|
+
for (const slot of attrSlots) {
|
|
19205
|
+
const varName = `__ra_${varSlotId(slot.slotId)}`;
|
|
19206
|
+
lines.push(`${indent} if (${varName}) {`);
|
|
19207
|
+
for (const attr of slot.attrs) {
|
|
19208
|
+
lines.push(`${indent} {`);
|
|
19209
|
+
for (const stmt of emitAttrUpdate(varName, attr.attrName, attr.wrappedExpression, attr.meta)) {
|
|
19210
|
+
lines.push(`${indent} ${stmt}`);
|
|
19211
|
+
}
|
|
19212
|
+
lines.push(`${indent} }`);
|
|
19213
|
+
}
|
|
19214
|
+
lines.push(`${indent} }`);
|
|
19215
|
+
}
|
|
19216
|
+
if (preambleRegions.length > 0 && mapPreambleWrapped) {
|
|
19217
|
+
lines.push(`${indent} ${mapPreambleWrapped}`);
|
|
19218
|
+
}
|
|
19219
|
+
for (const text of outerTexts) {
|
|
19220
|
+
lines.push(`${indent} ${writer}('${text.slotId}', String(${text.wrappedExpression}))`);
|
|
19221
|
+
}
|
|
19222
|
+
for (const region of preambleRegions) {
|
|
19223
|
+
lines.push(`${indent} ${writer}('${region.slotId}', ${region.valueExpr})`);
|
|
18799
19224
|
}
|
|
19225
|
+
lines.push(`${indent}})`);
|
|
18800
19226
|
}
|
|
18801
|
-
function
|
|
18802
|
-
|
|
18803
|
-
|
|
18804
|
-
|
|
18805
|
-
|
|
18806
|
-
|
|
19227
|
+
function emitOuterTexts(lines, indent, elVar, texts, bindingBfId, textClaimPathExprs) {
|
|
19228
|
+
if (texts.length === 0) return;
|
|
19229
|
+
const slots = texts.map((t) => ({
|
|
19230
|
+
id: t.slotId,
|
|
19231
|
+
kind: "text",
|
|
19232
|
+
path: [],
|
|
19233
|
+
pathExpr: textClaimPathExprs?.get(t.slotId)
|
|
19234
|
+
}));
|
|
19235
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
19236
|
+
lines.push(`${indent}const ${writer} = lazySlots(${elVar}, ${claimPlanLiteral(slots)})`);
|
|
19237
|
+
for (const text of texts) {
|
|
19238
|
+
lines.push(`${indent}createEffect(() => { ${writer}('${text.slotId}', String(${text.wrappedExpression})) }${bindingBfId(text.slotId)})`);
|
|
18807
19239
|
}
|
|
18808
|
-
lines.push(`${indent}if (${varName}) createEffect(() => { ${varName}.textContent = String(${text.wrappedExpression}) }${bfId}) }`);
|
|
18809
19240
|
}
|
|
18810
19241
|
function emitOuterConditional(lines, indent, elVar, cond, pc) {
|
|
18811
19242
|
const armIndent = `${indent} `;
|
|
@@ -18827,6 +19258,7 @@ var init_reactive_effects = __esm({
|
|
|
18827
19258
|
init_utils();
|
|
18828
19259
|
init_emit_reactive();
|
|
18829
19260
|
init_loop_child_arm();
|
|
19261
|
+
init_claim_plan();
|
|
18830
19262
|
}
|
|
18831
19263
|
});
|
|
18832
19264
|
|
|
@@ -18978,8 +19410,24 @@ function stringifyPlainLoop(lines, plan, topIndent = " ") {
|
|
|
18978
19410
|
childRefs,
|
|
18979
19411
|
bodyIsMultiRoot,
|
|
18980
19412
|
anchored,
|
|
18981
|
-
anchorKeyExpr
|
|
19413
|
+
anchorKeyExpr,
|
|
19414
|
+
preambleRegions
|
|
18982
19415
|
} = plan;
|
|
19416
|
+
if (plan.flatMapLeafItem) {
|
|
19417
|
+
const loopBfIdArg = plan.profileLoopId ? `, ${JSON.stringify(plan.profileLoopId)}` : "";
|
|
19418
|
+
lines.push(`${topIndent}mapArray(() => ${arrayExpr}, ${containerVar}, ${keyFn}, (__bfD, ${indexParam}, __existing) => {`);
|
|
19419
|
+
lines.push(`${topIndent} let __el = __existing`);
|
|
19420
|
+
lines.push(`${topIndent} if (!__el) { const __tpl = document.createElement('template'); __tpl.innerHTML = __bfD().h; __el = __tpl.content.firstElementChild }`);
|
|
19421
|
+
lines.push(`${topIndent} let __last = __existing ? undefined : __bfD().h`);
|
|
19422
|
+
lines.push(`${topIndent} createEffect(() => {`);
|
|
19423
|
+
lines.push(`${topIndent} const __html = __bfD().h`);
|
|
19424
|
+
lines.push(`${topIndent} if (__last === undefined) { __last = __html; return }`);
|
|
19425
|
+
lines.push(`${topIndent} if (__html !== __last) { __last = __html; patchLeaf(__el, __html) }`);
|
|
19426
|
+
lines.push(`${topIndent} })`);
|
|
19427
|
+
lines.push(`${topIndent} return __el`);
|
|
19428
|
+
lines.push(`${topIndent}}, '${markerId}'${loopBfIdArg})`);
|
|
19429
|
+
return;
|
|
19430
|
+
}
|
|
18983
19431
|
if (anchored) {
|
|
18984
19432
|
stringifyAnchoredLoop(lines, plan, topIndent, anchorKeyExpr);
|
|
18985
19433
|
return;
|
|
@@ -18990,7 +19438,7 @@ function stringifyPlainLoop(lines, plan, topIndent = " ") {
|
|
|
18990
19438
|
emitHoistedTemplateDecl(lines, topIndent, tplVar, hoistedTpl);
|
|
18991
19439
|
}
|
|
18992
19440
|
const loopBfId = plan.profileLoopId ? `, ${JSON.stringify(plan.profileLoopId)}` : "";
|
|
18993
|
-
if (reactiveEffects === null && !bodyIsMultiRoot && childRefs.length === 0) {
|
|
19441
|
+
if (reactiveEffects === null && !bodyIsMultiRoot && childRefs.length === 0 && preambleRegions.length === 0) {
|
|
18994
19442
|
const unwrapInline = paramUnwrap ? `${paramUnwrap} ` : "";
|
|
18995
19443
|
const preamble = mapPreambleWrapped ? `${mapPreambleWrapped}; ` : "";
|
|
18996
19444
|
const cloneExpr = hoistedTpl ? `return ${hoistedCloneExpr(tplVar, hoistedTpl)}` : emitTemplateCloneInline(template);
|
|
@@ -19019,22 +19467,30 @@ function stringifyPlainLoop(lines, plan, topIndent = " ") {
|
|
|
19019
19467
|
...reactiveEffects?.attrSlots.map((s) => s.slotId) ?? [],
|
|
19020
19468
|
...childRefs.map((r2) => r2.childSlotId)
|
|
19021
19469
|
];
|
|
19022
|
-
|
|
19023
|
-
|
|
19024
|
-
const built = buildSkeletonPathPlan(plan.skeletonPaths, "__el", { elementSlotIds, textSlotIds });
|
|
19470
|
+
if (elementSlotIds.length > 0) {
|
|
19471
|
+
const built = buildSkeletonPathPlan(plan.skeletonPaths, "__el", { elementSlotIds, textSlotIds: [] });
|
|
19025
19472
|
if (built.arrayElems.length > 0) {
|
|
19026
19473
|
pathPlan = built;
|
|
19027
19474
|
lines.push(`${bodyIndent}const __p = __existing ? null : [${built.arrayElems.join(", ")}]`);
|
|
19028
19475
|
}
|
|
19029
19476
|
}
|
|
19030
19477
|
}
|
|
19031
|
-
|
|
19478
|
+
const textClaimPathExprs = /* @__PURE__ */ new Map();
|
|
19479
|
+
if (hoistedTpl && plan.skeletonPaths) {
|
|
19480
|
+
for (const text of reactiveEffects?.outerTexts ?? []) {
|
|
19481
|
+
const path25 = plan.skeletonPaths.textMarkerPaths.get(text.slotId);
|
|
19482
|
+
if (path25) textClaimPathExprs.set(text.slotId, `__existing ? [] : [${path25.join(", ")}]`);
|
|
19483
|
+
}
|
|
19484
|
+
}
|
|
19485
|
+
if (reactiveEffects !== null || preambleRegions.length > 0) {
|
|
19032
19486
|
stringifyReactiveEffects(lines, reactiveEffects, {
|
|
19033
19487
|
indent: bodyIndent,
|
|
19034
19488
|
elVar: "__el",
|
|
19035
19489
|
bodyIsMultiRoot,
|
|
19036
19490
|
elementIndexBySlot: pathPlan?.elementIndexBySlot,
|
|
19037
|
-
|
|
19491
|
+
textClaimPathExprs,
|
|
19492
|
+
preambleRegions,
|
|
19493
|
+
mapPreambleWrapped
|
|
19038
19494
|
});
|
|
19039
19495
|
}
|
|
19040
19496
|
emitLoopChildRefs(lines, childRefs, { indent: bodyIndent, elVar: "__el", bodyIsMultiRoot, elementIndexBySlot: pathPlan?.elementIndexBySlot });
|
|
@@ -19138,10 +19594,13 @@ function stringifyStaticLoop(lines, plan) {
|
|
|
19138
19594
|
}
|
|
19139
19595
|
lines.push(` }`);
|
|
19140
19596
|
}
|
|
19141
|
-
|
|
19142
|
-
const
|
|
19143
|
-
|
|
19144
|
-
lines.push(`
|
|
19597
|
+
if (texts.length > 0) {
|
|
19598
|
+
const slots = texts.map((t) => ({ id: t.slotId, kind: "text", path: [] }));
|
|
19599
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
19600
|
+
lines.push(` const ${writer} = lazySlots(__iterEl, ${claimPlanLiteral(slots)})`);
|
|
19601
|
+
for (const text of texts) {
|
|
19602
|
+
lines.push(` createEffect(() => { ${writer}('${text.slotId}', String(${text.expression})) }${profileBindingId(pc, text.slotId)})`);
|
|
19603
|
+
}
|
|
19145
19604
|
}
|
|
19146
19605
|
emitLoopChildRefs(lines, childRefs, { indent: " ", elVar: "__iterEl", bodyIsMultiRoot: false });
|
|
19147
19606
|
lines.push(` }`);
|
|
@@ -19159,6 +19618,7 @@ var init_loop = __esm({
|
|
|
19159
19618
|
init_skeleton_paths();
|
|
19160
19619
|
init_component_loop();
|
|
19161
19620
|
init_composite_loop();
|
|
19621
|
+
init_claim_plan();
|
|
19162
19622
|
}
|
|
19163
19623
|
});
|
|
19164
19624
|
|
|
@@ -19214,13 +19674,18 @@ function emitReactive(lines, inner, indent, pc) {
|
|
|
19214
19674
|
if (inner.childLevels.length > 0) {
|
|
19215
19675
|
stringifyInnerLoops(lines, inner.childLevels, `${indent} `, pc);
|
|
19216
19676
|
}
|
|
19217
|
-
|
|
19677
|
+
const conditionalTexts = emit.reactiveTexts.filter((t) => t.insideConditional);
|
|
19678
|
+
const plainTexts = emit.reactiveTexts.filter((t) => !t.insideConditional);
|
|
19679
|
+
for (const text of conditionalTexts) {
|
|
19218
19680
|
const bf = profileBindingId(pc, text.slotId);
|
|
19219
|
-
|
|
19220
|
-
|
|
19221
|
-
|
|
19222
|
-
|
|
19223
|
-
|
|
19681
|
+
lines.push(`${indent} createEffect(() => { claimSlots(__innerEl${uid}, [{ id: '${text.slotId}', kind: 'text', path: [] }]).write('${text.slotId}', String(${text.wrappedExpression})) }${bf})`);
|
|
19682
|
+
}
|
|
19683
|
+
if (plainTexts.length > 0) {
|
|
19684
|
+
const slots = plainTexts.map((t) => ({ id: t.slotId, kind: "text", path: [] }));
|
|
19685
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
19686
|
+
lines.push(`${indent} const ${writer} = lazySlots(__innerEl${uid}, ${claimPlanLiteral(slots)})`);
|
|
19687
|
+
for (const text of plainTexts) {
|
|
19688
|
+
lines.push(`${indent} createEffect(() => { ${writer}('${text.slotId}', String(${text.wrappedExpression})) }${profileBindingId(pc, text.slotId)})`);
|
|
19224
19689
|
}
|
|
19225
19690
|
}
|
|
19226
19691
|
for (const attr of emit.reactiveAttrs) {
|
|
@@ -19282,6 +19747,7 @@ var init_inner_loop = __esm({
|
|
|
19282
19747
|
init_emit_reactive();
|
|
19283
19748
|
init_template_parse();
|
|
19284
19749
|
init_loop();
|
|
19750
|
+
init_claim_plan();
|
|
19285
19751
|
}
|
|
19286
19752
|
});
|
|
19287
19753
|
|
|
@@ -19370,6 +19836,11 @@ function indexBindingLine(handler, indexParam, indexExpr) {
|
|
|
19370
19836
|
if (!extractFreeIdentifiersFromText(handler).has(indexParam)) return null;
|
|
19371
19837
|
return `const ${indexParam} = ${indexExpr}`;
|
|
19372
19838
|
}
|
|
19839
|
+
function preambleLineForHandler(mapPreamble, declaredNames, handler) {
|
|
19840
|
+
if (!mapPreamble || declaredNames.length === 0) return null;
|
|
19841
|
+
const free = extractFreeIdentifiersFromText(handler);
|
|
19842
|
+
return declaredNames.some((name2) => free.has(name2)) ? mapPreamble : null;
|
|
19843
|
+
}
|
|
19373
19844
|
function stringifyEventDelegation(lines, plan) {
|
|
19374
19845
|
const { containerVar, events, itemLookup, profileComponentName } = plan;
|
|
19375
19846
|
const eventsByName = /* @__PURE__ */ new Map();
|
|
@@ -19414,7 +19885,8 @@ function stringifyEventDelegation(lines, plan) {
|
|
|
19414
19885
|
}
|
|
19415
19886
|
}
|
|
19416
19887
|
function emitKeyedLookup(ls, ev, handlerCall, lookup) {
|
|
19417
|
-
const { arrayExpr, param, keyWithItem, mapPreamble, hasBindings, indexParam } = lookup;
|
|
19888
|
+
const { arrayExpr, param, keyWithItem, mapPreamble, mapPreambleDeclaredNames, hasBindings, indexParam } = lookup;
|
|
19889
|
+
const preambleLine = preambleLineForHandler(mapPreamble, mapPreambleDeclaredNames, ev.handler);
|
|
19418
19890
|
if (ev.nestedLoops.length === 0) {
|
|
19419
19891
|
const idxLine2 = indexBindingLine(ev.handler, indexParam, `${arrayExpr}.findIndex(item => String(${keyWithItem}) === key)`);
|
|
19420
19892
|
ls.push(` const li = ${varSlotId(ev.childSlotId)}El.closest('[${BF_KEY}]')`);
|
|
@@ -19424,15 +19896,17 @@ function emitKeyedLookup(ls, ev, handlerCall, lookup) {
|
|
|
19424
19896
|
ls.push(` const __bfLoopItem = ${arrayExpr}.find(item => String(${keyWithItem}) === key)`);
|
|
19425
19897
|
ls.push(` if (__bfLoopItem) {`);
|
|
19426
19898
|
ls.push(` const ${param} = __bfLoopItem`);
|
|
19427
|
-
if (
|
|
19899
|
+
if (preambleLine) ls.push(` ${preambleLine}`);
|
|
19428
19900
|
if (idxLine2) ls.push(` ${idxLine2}`);
|
|
19429
|
-
ls.push(`
|
|
19901
|
+
ls.push(` ;${handlerCall}`);
|
|
19430
19902
|
ls.push(` }`);
|
|
19431
19903
|
} else {
|
|
19432
19904
|
ls.push(` const ${param} = ${arrayExpr}.find(item => String(${keyWithItem}) === key)`);
|
|
19433
|
-
|
|
19434
|
-
if (
|
|
19435
|
-
|
|
19905
|
+
ls.push(` if (${param}) {`);
|
|
19906
|
+
if (preambleLine) ls.push(` ${preambleLine}`);
|
|
19907
|
+
if (idxLine2) ls.push(` ${idxLine2}`);
|
|
19908
|
+
ls.push(` ;${handlerCall}`);
|
|
19909
|
+
ls.push(` }`);
|
|
19436
19910
|
}
|
|
19437
19911
|
ls.push(` }`);
|
|
19438
19912
|
return;
|
|
@@ -19459,13 +19933,16 @@ function emitKeyedLookup(ls, ev, handlerCall, lookup) {
|
|
|
19459
19933
|
}
|
|
19460
19934
|
const outerGuard = hasBindings ? "__bfLoopItem" : param;
|
|
19461
19935
|
const allParams = [outerGuard, ...ev.nestedLoops.map((n) => n.param)];
|
|
19462
|
-
if (mapPreamble) ls.push(` ${mapPreamble}`);
|
|
19463
19936
|
const idxLine = indexBindingLine(ev.handler, indexParam, `${arrayExpr}.findIndex(item => String(${keyWithItem}) === outerKey)`);
|
|
19464
|
-
|
|
19465
|
-
|
|
19937
|
+
ls.push(` if (${allParams.join(" && ")}) {`);
|
|
19938
|
+
if (preambleLine) ls.push(` ${preambleLine}`);
|
|
19939
|
+
if (idxLine) ls.push(` ${idxLine}`);
|
|
19940
|
+
ls.push(` ;${handlerCall}`);
|
|
19941
|
+
ls.push(` }`);
|
|
19466
19942
|
}
|
|
19467
19943
|
function emitDynamicIndexLookup(ls, ev, handlerCall, lookup) {
|
|
19468
|
-
const { arrayExpr, param, mapPreamble, hasBindings, indexParam } = lookup;
|
|
19944
|
+
const { arrayExpr, param, mapPreamble, mapPreambleDeclaredNames, hasBindings, indexParam } = lookup;
|
|
19945
|
+
const preambleLine = preambleLineForHandler(mapPreamble, mapPreambleDeclaredNames, ev.handler);
|
|
19469
19946
|
const idxLine = indexBindingLine(ev.handler, indexParam, "idx");
|
|
19470
19947
|
ls.push(` const li = ${varSlotId(ev.childSlotId)}El.closest('li, [bf-i]')`);
|
|
19471
19948
|
ls.push(` if (li && li.parentElement) {`);
|
|
@@ -19474,20 +19951,23 @@ function emitDynamicIndexLookup(ls, ev, handlerCall, lookup) {
|
|
|
19474
19951
|
ls.push(` const __bfLoopItem = ${arrayExpr}[idx]`);
|
|
19475
19952
|
ls.push(` if (__bfLoopItem) {`);
|
|
19476
19953
|
ls.push(` const ${param} = __bfLoopItem`);
|
|
19477
|
-
if (
|
|
19954
|
+
if (preambleLine) ls.push(` ${preambleLine}`);
|
|
19478
19955
|
if (idxLine) ls.push(` ${idxLine}`);
|
|
19479
|
-
ls.push(`
|
|
19956
|
+
ls.push(` ;${handlerCall}`);
|
|
19480
19957
|
ls.push(` }`);
|
|
19481
19958
|
} else {
|
|
19482
19959
|
ls.push(` const ${param} = ${arrayExpr}[idx]`);
|
|
19483
|
-
|
|
19484
|
-
if (
|
|
19485
|
-
|
|
19960
|
+
ls.push(` if (${param}) {`);
|
|
19961
|
+
if (preambleLine) ls.push(` ${preambleLine}`);
|
|
19962
|
+
if (idxLine) ls.push(` ${idxLine}`);
|
|
19963
|
+
ls.push(` ;${handlerCall}`);
|
|
19964
|
+
ls.push(` }`);
|
|
19486
19965
|
}
|
|
19487
19966
|
ls.push(` }`);
|
|
19488
19967
|
}
|
|
19489
19968
|
function emitStaticIndexLookup(ls, ev, handlerCall, lookup, containerVar) {
|
|
19490
|
-
const { arrayExpr, param, mapPreamble, offset: offset2, indexParam } = lookup;
|
|
19969
|
+
const { arrayExpr, param, mapPreamble, mapPreambleDeclaredNames, offset: offset2, indexParam } = lookup;
|
|
19970
|
+
const preambleLine = preambleLineForHandler(mapPreamble, mapPreambleDeclaredNames, ev.handler);
|
|
19491
19971
|
const idxLine = indexBindingLine(ev.handler, indexParam, "__idx");
|
|
19492
19972
|
ls.push(` let __el = ${varSlotId(ev.childSlotId)}El`);
|
|
19493
19973
|
ls.push(` while (__el.parentElement && __el.parentElement !== ${containerVar}) __el = __el.parentElement`);
|
|
@@ -19495,9 +19975,11 @@ function emitStaticIndexLookup(ls, ev, handlerCall, lookup, containerVar) {
|
|
|
19495
19975
|
const idxOffset = buildLoopChildIndexSubtraction(offset2 ?? void 0);
|
|
19496
19976
|
ls.push(` const __idx = Array.from(${containerVar}.children).indexOf(__el)${idxOffset}`);
|
|
19497
19977
|
ls.push(` const ${param} = ${arrayExpr}[__idx]`);
|
|
19498
|
-
|
|
19499
|
-
if (
|
|
19500
|
-
|
|
19978
|
+
ls.push(` if (${param}) {`);
|
|
19979
|
+
if (preambleLine) ls.push(` ${preambleLine}`);
|
|
19980
|
+
if (idxLine) ls.push(` ${idxLine}`);
|
|
19981
|
+
ls.push(` ;${handlerCall}`);
|
|
19982
|
+
ls.push(` }`);
|
|
19501
19983
|
ls.push(` }`);
|
|
19502
19984
|
}
|
|
19503
19985
|
var NON_BUBBLING_EVENTS;
|
|
@@ -19548,12 +20030,29 @@ function emitPlain(lines, plan) {
|
|
|
19548
20030
|
eventDelegation,
|
|
19549
20031
|
childRefs,
|
|
19550
20032
|
bodyIsMultiRoot,
|
|
19551
|
-
profileLoopId
|
|
20033
|
+
profileLoopId,
|
|
20034
|
+
preambleRegions
|
|
19552
20035
|
} = plan;
|
|
19553
20036
|
const loopBfId = profileLoopId ? `, ${JSON.stringify(profileLoopId)}` : "";
|
|
19554
20037
|
const unwrapInline = paramUnwrap ? `${paramUnwrap} ` : "";
|
|
19555
20038
|
lines.push(` __disposers.push(createDisposableEffect(() => {`);
|
|
19556
|
-
if (
|
|
20039
|
+
if (plan.flatMapLeafItem) {
|
|
20040
|
+
lines.push(` if (${containerVar}) mapArray(() => ${arrayExpr}, ${containerVar}, ${keyFn}, (__bfD, ${indexParam}, __existing) => {`);
|
|
20041
|
+
lines.push(` let __el = __existing`);
|
|
20042
|
+
lines.push(` if (!__el) { const __tpl = document.createElement('template'); __tpl.innerHTML = __bfD().h; __el = __tpl.content.firstElementChild }`);
|
|
20043
|
+
lines.push(` let __last = __existing ? undefined : __bfD().h`);
|
|
20044
|
+
lines.push(` createEffect(() => {`);
|
|
20045
|
+
lines.push(` const __html = __bfD().h`);
|
|
20046
|
+
lines.push(` if (__last === undefined) { __last = __html; return }`);
|
|
20047
|
+
lines.push(` if (__html !== __last) { __last = __html; patchLeaf(__el, __html) }`);
|
|
20048
|
+
lines.push(` })`);
|
|
20049
|
+
lines.push(` return __el`);
|
|
20050
|
+
lines.push(` }, '${markerId}'${loopBfId})`);
|
|
20051
|
+
lines.push(` }))`);
|
|
20052
|
+
stringifyEventDelegation(lines, eventDelegation);
|
|
20053
|
+
return;
|
|
20054
|
+
}
|
|
20055
|
+
if (reactiveEffects === null && !bodyIsMultiRoot && childRefs.length === 0 && preambleRegions.length === 0) {
|
|
19557
20056
|
const cloneExpr = emitTemplateCloneInline(template);
|
|
19558
20057
|
if (mapPreambleWrapped) {
|
|
19559
20058
|
lines.push(` if (${containerVar}) mapArray(() => ${arrayExpr}, ${containerVar}, ${keyFn}, (${paramHead}, ${indexParam}, __existing) => { ${unwrapInline}if (__existing) return __existing; ${mapPreambleWrapped}; ${cloneExpr} }, '${markerId}'${loopBfId})`);
|
|
@@ -19574,8 +20073,14 @@ function emitPlain(lines, plan) {
|
|
|
19574
20073
|
indent: " ",
|
|
19575
20074
|
singleRootLayout: "inline"
|
|
19576
20075
|
});
|
|
19577
|
-
if (reactiveEffects !== null) {
|
|
19578
|
-
stringifyReactiveEffects(lines, reactiveEffects, {
|
|
20076
|
+
if (reactiveEffects !== null || preambleRegions.length > 0) {
|
|
20077
|
+
stringifyReactiveEffects(lines, reactiveEffects, {
|
|
20078
|
+
indent: " ",
|
|
20079
|
+
elVar: "__el",
|
|
20080
|
+
bodyIsMultiRoot,
|
|
20081
|
+
preambleRegions,
|
|
20082
|
+
mapPreambleWrapped
|
|
20083
|
+
});
|
|
19579
20084
|
}
|
|
19580
20085
|
emitLoopChildRefs(lines, childRefs, { indent: " ", elVar: "__el", bodyIsMultiRoot });
|
|
19581
20086
|
lines.push(` return __el`);
|
|
@@ -19668,13 +20173,13 @@ function emitArmBody(lines, body2, mode2, indent, profileComponentName) {
|
|
|
19668
20173
|
}
|
|
19669
20174
|
lines.push(`${indent}} }`);
|
|
19670
20175
|
}
|
|
19671
|
-
|
|
19672
|
-
const
|
|
19673
|
-
|
|
19674
|
-
lines.push(`${indent}
|
|
19675
|
-
|
|
19676
|
-
|
|
19677
|
-
|
|
20176
|
+
if (body2.textEffects.length > 0) {
|
|
20177
|
+
const slots = body2.textEffects.map((te) => ({ id: te.slotId, kind: "markup", path: [] }));
|
|
20178
|
+
const writer = claimWriterVarName(slots, varSlotId);
|
|
20179
|
+
lines.push(`${indent}const ${writer} = lazySlots(__branchScope, ${claimPlanLiteral(slots)})`);
|
|
20180
|
+
for (const te of body2.textEffects) {
|
|
20181
|
+
lines.push(`${indent}__disposers.push(createDisposableEffect(() => { ${writer}('${te.slotId}', escapeTextOrNode(${te.expression})) }${bindingBfId(te.slotId)}))`);
|
|
20182
|
+
}
|
|
19678
20183
|
}
|
|
19679
20184
|
if (body2.loops.length > 0) {
|
|
19680
20185
|
stringifyBranchLoops(lines, body2.loops);
|
|
@@ -19707,6 +20212,7 @@ var init_insert = __esm({
|
|
|
19707
20212
|
init_branch_loop();
|
|
19708
20213
|
init_event_listener();
|
|
19709
20214
|
init_component_scope();
|
|
20215
|
+
init_claim_plan();
|
|
19710
20216
|
}
|
|
19711
20217
|
});
|
|
19712
20218
|
|
|
@@ -19795,6 +20301,31 @@ function buildPlainLoopPlan(elem, profileComponentName) {
|
|
|
19795
20301
|
const wrap = (expr) => wrapLoopParamAsAccessor(expr, elem.param, elem.paramBindings);
|
|
19796
20302
|
const { head: paramHead, unwrap: paramUnwrap } = destructureLoopParam(elem.param, elem.paramBindings);
|
|
19797
20303
|
const hasReactive2 = elem.bindings.reactiveAttrs.length > 0 || elem.bindings.reactiveTexts.length > 0 || elem.bindings.conditionals.length > 0;
|
|
20304
|
+
if (elem.flatMapClient) {
|
|
20305
|
+
return {
|
|
20306
|
+
kind: "plain",
|
|
20307
|
+
rowConstruction: "string-template",
|
|
20308
|
+
containerVar: `_${varSlotId(elem.slotId)}`,
|
|
20309
|
+
markerId: elem.markerId,
|
|
20310
|
+
profileLoopId: profileComponentName ? `${profileComponentName}#binding:${elem.slotId}` : void 0,
|
|
20311
|
+
arrayExpr: `(${buildChainedArrayExpr(elem)}).flatMap(${elem.flatMapClient.params} => ${elem.flatMapClient.body})`,
|
|
20312
|
+
keyFn: elem.flatMapClient.keyed ? "(__bfD, __bfI) => String(__bfD.k ?? __bfI)" : "null",
|
|
20313
|
+
paramHead: "__bfD",
|
|
20314
|
+
paramUnwrap: "",
|
|
20315
|
+
indexParam: "__idx",
|
|
20316
|
+
mapPreambleWrapped: "",
|
|
20317
|
+
template: "",
|
|
20318
|
+
reactiveEffects: null,
|
|
20319
|
+
childRefs: [],
|
|
20320
|
+
bodyIsMultiRoot: false,
|
|
20321
|
+
anchored: false,
|
|
20322
|
+
anchorKeyExpr: "__idx",
|
|
20323
|
+
flatMapLeafItem: true,
|
|
20324
|
+
// flatMap loops carry no `MapCallbackPreamble` (jsx-to-ir.ts drops it
|
|
20325
|
+
// for flatMapCallback), so there is nothing to patch here.
|
|
20326
|
+
preambleRegions: []
|
|
20327
|
+
};
|
|
20328
|
+
}
|
|
19798
20329
|
return {
|
|
19799
20330
|
kind: "plain",
|
|
19800
20331
|
rowConstruction: "string-template",
|
|
@@ -19818,6 +20349,7 @@ function buildPlainLoopPlan(elem, profileComponentName) {
|
|
|
19818
20349
|
skeletonPaths: elem.skeletonPaths,
|
|
19819
20350
|
reactiveEffects: hasReactive2 ? buildLoopReactiveEffectsPlan(elem, profileComponentName) : null,
|
|
19820
20351
|
childRefs: buildChildRefBindings(elem.bindings.refs, elem.param, elem.paramBindings),
|
|
20352
|
+
preambleRegions: buildPreambleRegionPlans(elem.preambleRegions, elem.param, elem.paramBindings),
|
|
19821
20353
|
bodyIsMultiRoot: elem.bodyIsMultiRoot ?? false,
|
|
19822
20354
|
anchored: elem.bodyIsItemConditional ?? false,
|
|
19823
20355
|
// Fall back to the iteration index when the loop has no key. A whole-item
|
|
@@ -19944,7 +20476,6 @@ var init_control_flow = __esm({
|
|
|
19944
20476
|
// ../jsx/src/ir-to-client-js/element-refs.ts
|
|
19945
20477
|
function generateElementRefs(ctx2) {
|
|
19946
20478
|
const regularSlots = /* @__PURE__ */ new Set();
|
|
19947
|
-
const textSlots = /* @__PURE__ */ new Set();
|
|
19948
20479
|
const componentSlots = /* @__PURE__ */ new Set();
|
|
19949
20480
|
const conditionalSlotIds = collectConditionalSlotIds(ctx2);
|
|
19950
20481
|
for (const elem of ctx2.interactiveElements) {
|
|
@@ -19952,11 +20483,6 @@ function generateElementRefs(ctx2) {
|
|
|
19952
20483
|
regularSlots.add(elem.slotId);
|
|
19953
20484
|
}
|
|
19954
20485
|
}
|
|
19955
|
-
for (const elem of ctx2.dynamicElements) {
|
|
19956
|
-
if (!elem.insideConditional) {
|
|
19957
|
-
textSlots.add(elem.slotId);
|
|
19958
|
-
}
|
|
19959
|
-
}
|
|
19960
20486
|
for (const elem of ctx2.conditionalElements) {
|
|
19961
20487
|
regularSlots.add(elem.slotId);
|
|
19962
20488
|
}
|
|
@@ -19985,10 +20511,9 @@ function generateElementRefs(ctx2) {
|
|
|
19985
20511
|
for (const slotId of componentSlots) {
|
|
19986
20512
|
regularSlots.delete(slotId);
|
|
19987
20513
|
}
|
|
19988
|
-
if (regularSlots.size === 0 &&
|
|
20514
|
+
if (regularSlots.size === 0 && componentSlots.size === 0) return "";
|
|
19989
20515
|
const refLines = [];
|
|
19990
20516
|
emitSlotRefs(refLines, [...regularSlots], "$");
|
|
19991
|
-
emitSlotRefs(refLines, [...textSlots], "$t");
|
|
19992
20517
|
emitSlotRefs(refLines, [...componentSlots], "$c");
|
|
19993
20518
|
return refLines.join("\n");
|
|
19994
20519
|
}
|
|
@@ -20638,6 +21163,107 @@ var init_ir_to_client_js = __esm({
|
|
|
20638
21163
|
}
|
|
20639
21164
|
});
|
|
20640
21165
|
|
|
21166
|
+
// ../jsx/src/ir-to-client-js/client-only-elision.ts
|
|
21167
|
+
function decideClientOnlyElision(root2) {
|
|
21168
|
+
walkNode(root2, [], /* @__PURE__ */ new Set(), { bailed: false });
|
|
21169
|
+
}
|
|
21170
|
+
function walkNode(node, path25, forceCloseAncestors, state2) {
|
|
21171
|
+
if (state2.bailed) return;
|
|
21172
|
+
if (node.type === "element") {
|
|
21173
|
+
if (!elementIsPathSafe(node.tag, flattenSkeletonChildren(node.children))) {
|
|
21174
|
+
state2.bailed = true;
|
|
21175
|
+
return;
|
|
21176
|
+
}
|
|
21177
|
+
const groupIdx = skeletonForceCloseGroup(node.tag);
|
|
21178
|
+
if (groupIdx >= 0 && forceCloseAncestors.has(groupIdx)) {
|
|
21179
|
+
state2.bailed = true;
|
|
21180
|
+
return;
|
|
21181
|
+
}
|
|
21182
|
+
const nextAncestors = groupIdx >= 0 ? /* @__PURE__ */ new Set([...forceCloseAncestors, groupIdx]) : forceCloseAncestors;
|
|
21183
|
+
walkChildren(flattenSkeletonChildren(node.children), path25, nextAncestors, state2);
|
|
21184
|
+
} else if (node.type === "fragment") {
|
|
21185
|
+
walkChildren(flattenSkeletonChildren(node.children), path25, forceCloseAncestors, state2);
|
|
21186
|
+
}
|
|
21187
|
+
}
|
|
21188
|
+
function walkChildren(children2, parentPath, forceCloseAncestors, state2) {
|
|
21189
|
+
let frozen = false;
|
|
21190
|
+
let idx = 0;
|
|
21191
|
+
let pendingText = false;
|
|
21192
|
+
for (let i = 0; i < children2.length; i++) {
|
|
21193
|
+
if (state2.bailed) return;
|
|
21194
|
+
const child = children2[i];
|
|
21195
|
+
switch (child.type) {
|
|
21196
|
+
case "text": {
|
|
21197
|
+
if (child.value === "") continue;
|
|
21198
|
+
if (!pendingText) idx += 1;
|
|
21199
|
+
pendingText = true;
|
|
21200
|
+
continue;
|
|
21201
|
+
}
|
|
21202
|
+
case "expression": {
|
|
21203
|
+
if (child.expr === "null" || child.expr === "undefined") continue;
|
|
21204
|
+
if (child.clientOnly && child.slotId) {
|
|
21205
|
+
const adjacent = isTextLike(children2[i - 1]) || isTextLike(children2[i + 1]);
|
|
21206
|
+
if (!frozen && !adjacent) {
|
|
21207
|
+
markElided(child, [...parentPath, idx]);
|
|
21208
|
+
frozen = true;
|
|
21209
|
+
} else {
|
|
21210
|
+
frozen = true;
|
|
21211
|
+
}
|
|
21212
|
+
idx += 1;
|
|
21213
|
+
pendingText = false;
|
|
21214
|
+
continue;
|
|
21215
|
+
}
|
|
21216
|
+
frozen = true;
|
|
21217
|
+
idx += 1;
|
|
21218
|
+
pendingText = false;
|
|
21219
|
+
continue;
|
|
21220
|
+
}
|
|
21221
|
+
case "element": {
|
|
21222
|
+
if (!elementIsPathSafe(child.tag, flattenSkeletonChildren(child.children))) {
|
|
21223
|
+
state2.bailed = true;
|
|
21224
|
+
return;
|
|
21225
|
+
}
|
|
21226
|
+
if (!frozen) {
|
|
21227
|
+
walkNode(child, [...parentPath, idx], forceCloseAncestors, state2);
|
|
21228
|
+
}
|
|
21229
|
+
idx += 1;
|
|
21230
|
+
pendingText = false;
|
|
21231
|
+
continue;
|
|
21232
|
+
}
|
|
21233
|
+
case "fragment":
|
|
21234
|
+
continue;
|
|
21235
|
+
// already flattened
|
|
21236
|
+
default:
|
|
21237
|
+
frozen = true;
|
|
21238
|
+
idx += 1;
|
|
21239
|
+
pendingText = false;
|
|
21240
|
+
continue;
|
|
21241
|
+
}
|
|
21242
|
+
}
|
|
21243
|
+
}
|
|
21244
|
+
function isTextLike(node) {
|
|
21245
|
+
if (!node) return false;
|
|
21246
|
+
if (node.type === "text") return node.value !== "";
|
|
21247
|
+
if (node.type === "expression") return node.expr !== "null" && node.expr !== "undefined";
|
|
21248
|
+
return false;
|
|
21249
|
+
}
|
|
21250
|
+
function markElided(expr, path25) {
|
|
21251
|
+
expr.markerless = true;
|
|
21252
|
+
expr.elidedPath = path25;
|
|
21253
|
+
}
|
|
21254
|
+
function elementIsPathSafe(tag, flatChildren) {
|
|
21255
|
+
if (SKELETON_PATH_HAZARD_TAGS.has(tag)) return false;
|
|
21256
|
+
if (VOID_ELEMENTS.has(tag) && flatChildren.length > 0) return false;
|
|
21257
|
+
if (tag === "tr" && hasForeignTableRowContent(flatChildren)) return false;
|
|
21258
|
+
return true;
|
|
21259
|
+
}
|
|
21260
|
+
var init_client_only_elision = __esm({
|
|
21261
|
+
"../jsx/src/ir-to-client-js/client-only-elision.ts"() {
|
|
21262
|
+
"use strict";
|
|
21263
|
+
init_html_template();
|
|
21264
|
+
}
|
|
21265
|
+
});
|
|
21266
|
+
|
|
20641
21267
|
// ../jsx/src/css-layer-prefixer.ts
|
|
20642
21268
|
function prefixClass(cls, layerName) {
|
|
20643
21269
|
if (!cls || cls.startsWith("layer-")) return cls;
|
|
@@ -21812,7 +22438,7 @@ function checkRichTypeMethodCalls(root2, metadata, errors) {
|
|
|
21812
22438
|
if (!metadata.propsType) return;
|
|
21813
22439
|
const matchers = prepareLoweringMatchers(metadata);
|
|
21814
22440
|
const seen = /* @__PURE__ */ new Set();
|
|
21815
|
-
|
|
22441
|
+
walkNode2(root2, metadata, EMPTY_BINDINGS2, matchers, errors, seen);
|
|
21816
22442
|
}
|
|
21817
22443
|
function isLoweringClaimed(matchers, callee, args2) {
|
|
21818
22444
|
return matchers.some((m) => m(callee, args2) !== null);
|
|
@@ -21940,7 +22566,7 @@ function walkAttrValue(value2, clientOnly, loc, meta, bindings, matchers, errors
|
|
|
21940
22566
|
walkTemplateParts(value2.parts, loc, meta, bindings, matchers, errors, seen);
|
|
21941
22567
|
}
|
|
21942
22568
|
}
|
|
21943
|
-
function
|
|
22569
|
+
function walkNode2(node, meta, bindings, matchers, errors, seen) {
|
|
21944
22570
|
if (node.type === "expression") {
|
|
21945
22571
|
if (!node.clientOnly && node.parsed) checkExpr(node.parsed, node.loc, meta, bindings, matchers, errors, seen);
|
|
21946
22572
|
} else if (node.type === "conditional") {
|
|
@@ -21960,11 +22586,11 @@ function walkNode(node, meta, bindings, matchers, errors, seen) {
|
|
|
21960
22586
|
case "component":
|
|
21961
22587
|
case "fragment":
|
|
21962
22588
|
case "provider":
|
|
21963
|
-
for (const child of node.children)
|
|
22589
|
+
for (const child of node.children) walkNode2(child, meta, bindings, matchers, errors, seen);
|
|
21964
22590
|
break;
|
|
21965
22591
|
case "async":
|
|
21966
|
-
|
|
21967
|
-
for (const child of node.children)
|
|
22592
|
+
walkNode2(node.fallback, meta, bindings, matchers, errors, seen);
|
|
22593
|
+
for (const child of node.children) walkNode2(child, meta, bindings, matchers, errors, seen);
|
|
21968
22594
|
break;
|
|
21969
22595
|
case "loop": {
|
|
21970
22596
|
if (node.clientOnly) break;
|
|
@@ -21973,29 +22599,29 @@ function walkNode(node, meta, bindings, matchers, errors, seen) {
|
|
|
21973
22599
|
const arrayType = node.arrayParsed ? resolveReceiverType(node.arrayParsed, meta, bindings) : null;
|
|
21974
22600
|
loopBindings.set(node.param, arrayType?.kind === "array" ? arrayType.elementType ?? null : null);
|
|
21975
22601
|
if (node.index) loopBindings.set(node.index, null);
|
|
21976
|
-
for (const child of node.children)
|
|
22602
|
+
for (const child of node.children) walkNode2(child, meta, loopBindings, matchers, errors, seen);
|
|
21977
22603
|
if (node.childComponent) {
|
|
21978
|
-
for (const child of node.childComponent.children)
|
|
22604
|
+
for (const child of node.childComponent.children) walkNode2(child, meta, loopBindings, matchers, errors, seen);
|
|
21979
22605
|
}
|
|
21980
22606
|
for (const nested of node.nestedComponents ?? []) {
|
|
21981
|
-
for (const child of nested.children)
|
|
22607
|
+
for (const child of nested.children) walkNode2(child, meta, loopBindings, matchers, errors, seen);
|
|
21982
22608
|
}
|
|
21983
22609
|
for (const seg of node.flatMapCallback?.segments ?? []) {
|
|
21984
|
-
if (seg.kind === "jsx")
|
|
22610
|
+
if (seg.kind === "jsx") walkNode2(seg.ir, meta, loopBindings, matchers, errors, seen);
|
|
21985
22611
|
}
|
|
21986
22612
|
for (const seg of node.preamble?.segments ?? []) {
|
|
21987
|
-
if (seg.kind === "jsx")
|
|
22613
|
+
if (seg.kind === "jsx") walkNode2(seg.ir, meta, loopBindings, matchers, errors, seen);
|
|
21988
22614
|
}
|
|
21989
22615
|
break;
|
|
21990
22616
|
}
|
|
21991
22617
|
case "conditional":
|
|
21992
22618
|
if (node.clientOnly) break;
|
|
21993
|
-
|
|
21994
|
-
|
|
22619
|
+
walkNode2(node.whenTrue, meta, bindings, matchers, errors, seen);
|
|
22620
|
+
walkNode2(node.whenFalse, meta, bindings, matchers, errors, seen);
|
|
21995
22621
|
break;
|
|
21996
22622
|
case "if-statement":
|
|
21997
|
-
|
|
21998
|
-
if (node.alternate)
|
|
22623
|
+
walkNode2(node.consequent, meta, bindings, matchers, errors, seen);
|
|
22624
|
+
if (node.alternate) walkNode2(node.alternate, meta, bindings, matchers, errors, seen);
|
|
21999
22625
|
break;
|
|
22000
22626
|
}
|
|
22001
22627
|
}
|
|
@@ -22068,6 +22694,7 @@ function compileMultipleComponents(source, filePath, componentNames, options2) {
|
|
|
22068
22694
|
};
|
|
22069
22695
|
componentIR.metadata.clientAnalysis = analyzeClientNeeds(componentIR);
|
|
22070
22696
|
checkRichTypeMethodCalls(componentIR.root, componentIR.metadata, errors);
|
|
22697
|
+
decideClientOnlyElision(componentIR.root);
|
|
22071
22698
|
if (options2.cssLayerPrefix) {
|
|
22072
22699
|
applyCssLayerPrefix(componentIR, options2.cssLayerPrefix);
|
|
22073
22700
|
}
|
|
@@ -22405,6 +23032,7 @@ function compileJSX(source, filePath, options2) {
|
|
|
22405
23032
|
};
|
|
22406
23033
|
componentIR.metadata.clientAnalysis = analyzeClientNeeds(componentIR);
|
|
22407
23034
|
checkRichTypeMethodCalls(componentIR.root, componentIR.metadata, errors);
|
|
23035
|
+
decideClientOnlyElision(componentIR.root);
|
|
22408
23036
|
if (ctx2.importedClientSignalNames.size > 0) {
|
|
22409
23037
|
const sources = /* @__PURE__ */ new Set();
|
|
22410
23038
|
for (const imp of ctx2.imports) {
|
|
@@ -22526,6 +23154,7 @@ var init_compiler = __esm({
|
|
|
22526
23154
|
init_jsx_to_ir();
|
|
22527
23155
|
init_builtins();
|
|
22528
23156
|
init_ir_to_client_js();
|
|
23157
|
+
init_client_only_elision();
|
|
22529
23158
|
init_emit_module_level();
|
|
22530
23159
|
init_imports();
|
|
22531
23160
|
init_component_scope();
|
|
@@ -26471,6 +27100,7 @@ __export(src_exports, {
|
|
|
26471
27100
|
createProgramForFile: () => createProgramForFile,
|
|
26472
27101
|
dangerousInnerHtmlDiagnostic: () => dangerousInnerHtmlDiagnostic,
|
|
26473
27102
|
dangerousInnerHtmlMetacharViolation: () => dangerousInnerHtmlMetacharViolation,
|
|
27103
|
+
decideClientOnlyElision: () => decideClientOnlyElision,
|
|
26474
27104
|
describeFallback: () => describeFallback,
|
|
26475
27105
|
diffProfiles: () => diffProfiles,
|
|
26476
27106
|
diffStaticBudget: () => diffStaticBudget,
|
|
@@ -26585,6 +27215,7 @@ var init_src2 = __esm({
|
|
|
26585
27215
|
init_analyzer();
|
|
26586
27216
|
init_shared_program();
|
|
26587
27217
|
init_jsx_to_ir();
|
|
27218
|
+
init_client_only_elision();
|
|
26588
27219
|
init_module_exports();
|
|
26589
27220
|
init_interface();
|
|
26590
27221
|
init_test_adapter();
|