@barefootjs/jsx 0.4.0 → 0.5.1
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/adapters/interface.d.ts +20 -0
- package/dist/adapters/interface.d.ts.map +1 -1
- package/dist/adapters/test-adapter.d.ts.map +1 -1
- package/dist/expression-parser.d.ts +36 -19
- package/dist/expression-parser.d.ts.map +1 -1
- package/dist/import-map.d.ts +56 -0
- package/dist/import-map.d.ts.map +1 -0
- package/dist/import-map.js +18 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +333 -199
- package/dist/ir-to-client-js/collect-elements.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/loop.d.ts +14 -0
- package/dist/ir-to-client-js/control-flow/plan/loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/emit-reactive.d.ts.map +1 -1
- package/dist/ir-to-client-js/html-template.d.ts +0 -14
- package/dist/ir-to-client-js/html-template.d.ts.map +1 -1
- package/dist/ir-to-client-js/imports.d.ts +2 -2
- package/dist/ir-to-client-js/imports.d.ts.map +1 -1
- package/dist/ir-to-client-js/reactivity.d.ts.map +1 -1
- package/dist/ir-to-client-js/types.d.ts +7 -0
- package/dist/ir-to-client-js/types.d.ts.map +1 -1
- package/dist/ir-to-client-js/utils.d.ts +2 -2
- package/dist/ir-to-client-js/utils.d.ts.map +1 -1
- package/dist/scanner/js-scanner.d.ts +10 -0
- package/dist/scanner/js-scanner.d.ts.map +1 -1
- package/dist/scanner/js-scanner.js +5 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -3
- package/src/__tests__/__snapshots__/doc-examples.test.ts.snap +438 -190
- package/src/__tests__/adapter-output.test.ts +49 -0
- package/src/__tests__/child-components-in-map.test.ts +76 -0
- package/src/__tests__/client-js-generation.test.ts +5 -2
- package/src/__tests__/import-map.test.ts +75 -0
- package/src/__tests__/inline-jsx-callback.test.ts +95 -0
- package/src/__tests__/ir-jsx-props.test.ts +5 -2
- package/src/__tests__/ir-sort-comparator.test.ts +212 -9
- package/src/__tests__/loop-item-conditional-codegen.test.ts +81 -0
- package/src/__tests__/map-logical-jsx-helper.test.ts +159 -0
- package/src/__tests__/missing-key-in-list.test.ts +49 -0
- package/src/__tests__/reactive-attrs-in-map.test.ts +41 -0
- package/src/__tests__/token-contains-ident.test.ts +27 -0
- package/src/__tests__/unsupported-expression.test.ts +42 -13
- package/src/adapters/interface.ts +20 -0
- package/src/adapters/test-adapter.ts +16 -1
- package/src/expression-parser.ts +265 -50
- package/src/import-map.ts +72 -0
- package/src/index.ts +5 -1
- package/src/ir-to-client-js/collect-elements.ts +3 -0
- package/src/ir-to-client-js/control-flow/plan/build-loop.ts +17 -0
- package/src/ir-to-client-js/control-flow/plan/loop.ts +14 -0
- package/src/ir-to-client-js/control-flow/stringify/insert.ts +7 -2
- package/src/ir-to-client-js/control-flow/stringify/loop.ts +60 -0
- package/src/ir-to-client-js/emit-reactive.ts +12 -3
- package/src/ir-to-client-js/html-template.ts +29 -3
- package/src/ir-to-client-js/imports.ts +2 -2
- package/src/ir-to-client-js/reactivity.ts +17 -1
- package/src/ir-to-client-js/stringify/static-array-child-init.ts +8 -4
- package/src/ir-to-client-js/types.ts +7 -0
- package/src/ir-to-client-js/utils.ts +31 -116
- package/src/jsx-to-ir.ts +161 -12
- package/src/preprocess-inline-jsx-callbacks.ts +28 -10
- package/src/scanner/js-scanner.ts +16 -1
- package/src/types.ts +12 -0
package/dist/index.js
CHANGED
|
@@ -62,6 +62,9 @@ function canRegexStartHere(prev) {
|
|
|
62
62
|
return true;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
function isIdentifierLikeToken(kind) {
|
|
66
|
+
return kind === ts.SyntaxKind.Identifier || kind >= ts.SyntaxKind.FirstKeyword && kind <= ts.SyntaxKind.LastKeyword;
|
|
67
|
+
}
|
|
65
68
|
function isOpaqueContentKind(kind) {
|
|
66
69
|
return kind === ts.SyntaxKind.StringLiteral || kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral || kind === ts.SyntaxKind.RegularExpressionLiteral || kind === ts.SyntaxKind.SingleLineCommentTrivia || kind === ts.SyntaxKind.MultiLineCommentTrivia;
|
|
67
70
|
}
|
|
@@ -173,6 +176,22 @@ function findTopLevelTemplateLiterals(code) {
|
|
|
173
176
|
return out;
|
|
174
177
|
}
|
|
175
178
|
|
|
179
|
+
// src/import-map.ts
|
|
180
|
+
function escapeHtmlAttr(value) {
|
|
181
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
182
|
+
}
|
|
183
|
+
function renderImportMapHtml(manifest) {
|
|
184
|
+
const imports = manifest.importmap?.imports ?? {};
|
|
185
|
+
const json = JSON.stringify({ imports }).replace(/</g, "\\u003c");
|
|
186
|
+
const lines = [`<script type="importmap">${json}</script>`];
|
|
187
|
+
for (const href of manifest.preloads ?? []) {
|
|
188
|
+
lines.push(`<link rel="modulepreload" href="${escapeHtmlAttr(href)}" crossorigin>`);
|
|
189
|
+
}
|
|
190
|
+
return lines.join(`
|
|
191
|
+
`) + `
|
|
192
|
+
`;
|
|
193
|
+
}
|
|
194
|
+
|
|
176
195
|
// src/analyzer.ts
|
|
177
196
|
import ts7 from "typescript";
|
|
178
197
|
|
|
@@ -203,6 +222,7 @@ import {
|
|
|
203
222
|
BF_LOOP_END,
|
|
204
223
|
loopStartMarker,
|
|
205
224
|
loopEndMarker,
|
|
225
|
+
loopItemMarker,
|
|
206
226
|
toHTMLAttrName as toHtmlAttrName
|
|
207
227
|
} from "@barefootjs/shared";
|
|
208
228
|
var PROPS_PARAM = "_p";
|
|
@@ -398,150 +418,17 @@ function setIntersects(a, b) {
|
|
|
398
418
|
function tokenContainsIdent(expr, ident) {
|
|
399
419
|
return scanForIdentifiers(expr, (token) => token === ident);
|
|
400
420
|
}
|
|
401
|
-
var IDENT_START_RE = /[A-Za-z_$]/;
|
|
402
|
-
var IDENT_PART_RE = /[A-Za-z0-9_$]/;
|
|
403
421
|
function scanForIdentifiers(expr, predicate) {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
case 0:
|
|
413
|
-
case 4: {
|
|
414
|
-
if (ch === "'") {
|
|
415
|
-
state = 1;
|
|
416
|
-
i++;
|
|
417
|
-
continue;
|
|
418
|
-
}
|
|
419
|
-
if (ch === '"') {
|
|
420
|
-
state = 2;
|
|
421
|
-
i++;
|
|
422
|
-
continue;
|
|
423
|
-
}
|
|
424
|
-
if (ch === "`") {
|
|
425
|
-
state = 3;
|
|
426
|
-
i++;
|
|
427
|
-
continue;
|
|
428
|
-
}
|
|
429
|
-
if (ch === "/" && i + 1 < n) {
|
|
430
|
-
const next = expr[i + 1];
|
|
431
|
-
if (next === "/") {
|
|
432
|
-
state = 5;
|
|
433
|
-
i += 2;
|
|
434
|
-
continue;
|
|
435
|
-
}
|
|
436
|
-
if (next === "*") {
|
|
437
|
-
state = 6;
|
|
438
|
-
i += 2;
|
|
439
|
-
continue;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
if (state === 4) {
|
|
443
|
-
if (ch === "{") {
|
|
444
|
-
braceDepth++;
|
|
445
|
-
i++;
|
|
446
|
-
continue;
|
|
447
|
-
}
|
|
448
|
-
if (ch === "}") {
|
|
449
|
-
if (braceDepth === 0) {
|
|
450
|
-
const restored = tmplExprStack.pop();
|
|
451
|
-
braceDepth = restored ?? 0;
|
|
452
|
-
state = 3;
|
|
453
|
-
i++;
|
|
454
|
-
continue;
|
|
455
|
-
}
|
|
456
|
-
braceDepth--;
|
|
457
|
-
i++;
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
if (IDENT_START_RE.test(ch)) {
|
|
462
|
-
let j = i + 1;
|
|
463
|
-
while (j < n && IDENT_PART_RE.test(expr[j]))
|
|
464
|
-
j++;
|
|
465
|
-
const token = expr.slice(i, j);
|
|
466
|
-
let prev = i - 1;
|
|
467
|
-
while (prev >= 0 && (expr[prev] === " " || expr[prev] === "\t" || expr[prev] === `
|
|
468
|
-
` || expr[prev] === "\r"))
|
|
469
|
-
prev--;
|
|
470
|
-
const isMemberTail = prev >= 0 && expr[prev] === "." && (prev === 0 || expr[prev - 1] !== ".");
|
|
471
|
-
if (!isMemberTail && predicate(token))
|
|
472
|
-
return true;
|
|
473
|
-
i = j;
|
|
474
|
-
continue;
|
|
475
|
-
}
|
|
476
|
-
i++;
|
|
477
|
-
continue;
|
|
478
|
-
}
|
|
479
|
-
case 1: {
|
|
480
|
-
if (ch === "\\" && i + 1 < n) {
|
|
481
|
-
i += 2;
|
|
482
|
-
continue;
|
|
483
|
-
}
|
|
484
|
-
if (ch === "'") {
|
|
485
|
-
state = 0;
|
|
486
|
-
i++;
|
|
487
|
-
continue;
|
|
488
|
-
}
|
|
489
|
-
i++;
|
|
490
|
-
continue;
|
|
491
|
-
}
|
|
492
|
-
case 2: {
|
|
493
|
-
if (ch === "\\" && i + 1 < n) {
|
|
494
|
-
i += 2;
|
|
495
|
-
continue;
|
|
496
|
-
}
|
|
497
|
-
if (ch === '"') {
|
|
498
|
-
state = 0;
|
|
499
|
-
i++;
|
|
500
|
-
continue;
|
|
501
|
-
}
|
|
502
|
-
i++;
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
case 3: {
|
|
506
|
-
if (ch === "\\" && i + 1 < n) {
|
|
507
|
-
i += 2;
|
|
508
|
-
continue;
|
|
509
|
-
}
|
|
510
|
-
if (ch === "`") {
|
|
511
|
-
state = tmplExprStack.length > 0 ? 4 : 0;
|
|
512
|
-
i++;
|
|
513
|
-
continue;
|
|
514
|
-
}
|
|
515
|
-
if (ch === "$" && i + 1 < n && expr[i + 1] === "{") {
|
|
516
|
-
tmplExprStack.push(braceDepth);
|
|
517
|
-
braceDepth = 0;
|
|
518
|
-
state = 4;
|
|
519
|
-
i += 2;
|
|
520
|
-
continue;
|
|
521
|
-
}
|
|
522
|
-
i++;
|
|
523
|
-
continue;
|
|
524
|
-
}
|
|
525
|
-
case 5: {
|
|
526
|
-
if (ch === `
|
|
527
|
-
` || ch === "\r") {
|
|
528
|
-
state = 0;
|
|
529
|
-
i++;
|
|
530
|
-
continue;
|
|
531
|
-
}
|
|
532
|
-
i++;
|
|
533
|
-
continue;
|
|
534
|
-
}
|
|
535
|
-
case 6: {
|
|
536
|
-
if (ch === "*" && i + 1 < n && expr[i + 1] === "/") {
|
|
537
|
-
state = 0;
|
|
538
|
-
i += 2;
|
|
539
|
-
continue;
|
|
540
|
-
}
|
|
541
|
-
i++;
|
|
542
|
-
continue;
|
|
543
|
-
}
|
|
422
|
+
let prevSignificant;
|
|
423
|
+
for (const tok of iterateJsTokens(expr)) {
|
|
424
|
+
if (isTriviaKind(tok.kind))
|
|
425
|
+
continue;
|
|
426
|
+
if (isIdentifierLikeToken(tok.kind)) {
|
|
427
|
+
const isMemberTail = prevSignificant === ts2.SyntaxKind.DotToken || prevSignificant === ts2.SyntaxKind.QuestionDotToken;
|
|
428
|
+
if (!isMemberTail && predicate(expr.slice(tok.pos, tok.end)))
|
|
429
|
+
return true;
|
|
544
430
|
}
|
|
431
|
+
prevSignificant = tok.kind;
|
|
545
432
|
}
|
|
546
433
|
return false;
|
|
547
434
|
}
|
|
@@ -1268,6 +1155,9 @@ function buildSpreadAttrsMergeCall(args) {
|
|
|
1268
1155
|
}
|
|
1269
1156
|
return `\${spreadAttrs({${objMembers.join(", ")}})}`;
|
|
1270
1157
|
}
|
|
1158
|
+
function itemAnchorTemplate(keyExpr) {
|
|
1159
|
+
return `<!--${loopItemMarker("${" + keyExpr + "}")}-->`;
|
|
1160
|
+
}
|
|
1271
1161
|
function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, branchSlotsVar, insideLoop = false, inHoistedChildren = false) {
|
|
1272
1162
|
const recurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth, loopParams, branchSlotsVar, insideLoop, inHoistedChildren);
|
|
1273
1163
|
const wrapExpr = (expr) => wrapExprWithLoopParams(expr, loopParams);
|
|
@@ -1363,7 +1253,10 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
|
|
|
1363
1253
|
}
|
|
1364
1254
|
case "loop": {
|
|
1365
1255
|
const innerRecurse = (n) => irToHtmlTemplate(n, restSpreadNames, loopDepth + 1, loopParams, branchSlotsVar, insideLoop);
|
|
1366
|
-
|
|
1256
|
+
let childTemplate = node.children.map(innerRecurse).join("");
|
|
1257
|
+
if (node.bodyIsItemConditional && node.key) {
|
|
1258
|
+
childTemplate = `${itemAnchorTemplate(node.key)}${childTemplate}`;
|
|
1259
|
+
}
|
|
1367
1260
|
const indexParam = node.index ? `, ${node.index}` : "";
|
|
1368
1261
|
const rawChainedArray = applyLoopChain(node);
|
|
1369
1262
|
const { array: iterArray, callbackParam } = applyIterationShape(node, rawChainedArray, indexParam);
|
|
@@ -1942,7 +1835,10 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
1942
1835
|
return `\${renderChild('${nameForRegistryRef(node.name)}', ${propsExpr}${keyArg || (slotArg ? ", undefined" : "")}${slotArg})}`;
|
|
1943
1836
|
}
|
|
1944
1837
|
case "loop": {
|
|
1945
|
-
|
|
1838
|
+
let childTemplate = node.children.map(recurseInLoop).join("");
|
|
1839
|
+
if (node.bodyIsItemConditional && node.key) {
|
|
1840
|
+
childTemplate = `${itemAnchorTemplate(node.key)}${childTemplate}`;
|
|
1841
|
+
}
|
|
1946
1842
|
const indexParam = node.index ? `, ${node.index}` : "";
|
|
1947
1843
|
const chainedTemplateArray = node.sortComparator || node.filterPredicate ? applyLoopChain(node, node.templateArray) : node.templateArray;
|
|
1948
1844
|
const rawArrayExpr = transformExpr(node.array, chainedTemplateArray);
|
|
@@ -5418,6 +5314,8 @@ function convertNode(node, raw) {
|
|
|
5418
5314
|
` + ` (a, b) => a.field - b.field
|
|
5419
5315
|
` + ` (a, b) => a.localeCompare(b)
|
|
5420
5316
|
` + ` (a, b) => a.field.localeCompare(b.field)
|
|
5317
|
+
` + ` (a, b) => a.field > b.field ? 1 : -1 (relational ternary)
|
|
5318
|
+
` + ` any of the above ||-chained for multi-key tie-breaks
|
|
5421
5319
|
` + `(reverse the operands for descending order). ` + `Wrap the call in /* @client */ to evaluate at hydration.`
|
|
5422
5320
|
};
|
|
5423
5321
|
}
|
|
@@ -5577,26 +5475,54 @@ function extractSortComparatorFromTS(node, method) {
|
|
|
5577
5475
|
const paramA = pA.name.text;
|
|
5578
5476
|
const paramB = pB.name.text;
|
|
5579
5477
|
let body;
|
|
5580
|
-
if (ts8.isArrowFunction(node)) {
|
|
5581
|
-
if (ts8.isBlock(node.body))
|
|
5582
|
-
return null;
|
|
5478
|
+
if (ts8.isArrowFunction(node) && !ts8.isBlock(node.body)) {
|
|
5583
5479
|
body = node.body;
|
|
5584
5480
|
} else {
|
|
5585
|
-
const
|
|
5481
|
+
const block = node.body;
|
|
5482
|
+
const stmts = block.statements;
|
|
5586
5483
|
if (stmts.length !== 1 || !ts8.isReturnStatement(stmts[0]) || !stmts[0].expression)
|
|
5587
5484
|
return null;
|
|
5588
5485
|
body = stmts[0].expression;
|
|
5589
5486
|
}
|
|
5590
5487
|
const raw = body.getText();
|
|
5488
|
+
const keys = [];
|
|
5489
|
+
for (const operand of flattenLogicalOr(body)) {
|
|
5490
|
+
const key = classifyLeafComparator(operand, paramA, paramB);
|
|
5491
|
+
if (!key)
|
|
5492
|
+
return null;
|
|
5493
|
+
keys.push(key);
|
|
5494
|
+
}
|
|
5495
|
+
if (keys.length === 0)
|
|
5496
|
+
return null;
|
|
5497
|
+
return { keys, raw, paramA, paramB, method };
|
|
5498
|
+
}
|
|
5499
|
+
function unwrapParens(expr) {
|
|
5500
|
+
let e = expr;
|
|
5501
|
+
while (ts8.isParenthesizedExpression(e))
|
|
5502
|
+
e = e.expression;
|
|
5503
|
+
return e;
|
|
5504
|
+
}
|
|
5505
|
+
function flattenLogicalOr(expr) {
|
|
5506
|
+
const inner = unwrapParens(expr);
|
|
5507
|
+
if (ts8.isBinaryExpression(inner) && inner.operatorToken.kind === ts8.SyntaxKind.BarBarToken) {
|
|
5508
|
+
return [...flattenLogicalOr(inner.left), ...flattenLogicalOr(inner.right)];
|
|
5509
|
+
}
|
|
5510
|
+
return [inner];
|
|
5511
|
+
}
|
|
5512
|
+
function classifyLeafComparator(expr, paramA, paramB) {
|
|
5513
|
+
const body = unwrapParens(expr);
|
|
5591
5514
|
if (ts8.isBinaryExpression(body) && body.operatorToken.kind === ts8.SyntaxKind.MinusToken) {
|
|
5592
|
-
return classifyComparatorOperands(body.left, body.right, paramA, paramB, "numeric"
|
|
5515
|
+
return classifyComparatorOperands(body.left, body.right, paramA, paramB, "numeric");
|
|
5593
5516
|
}
|
|
5594
5517
|
if (ts8.isCallExpression(body) && ts8.isPropertyAccessExpression(body.expression) && body.expression.name.text === "localeCompare" && body.arguments.length === 1) {
|
|
5595
|
-
return classifyComparatorOperands(body.expression.expression, body.arguments[0], paramA, paramB, "string"
|
|
5518
|
+
return classifyComparatorOperands(body.expression.expression, body.arguments[0], paramA, paramB, "string");
|
|
5519
|
+
}
|
|
5520
|
+
if (ts8.isConditionalExpression(body)) {
|
|
5521
|
+
return classifyTernaryComparator(body, paramA, paramB);
|
|
5596
5522
|
}
|
|
5597
5523
|
return null;
|
|
5598
5524
|
}
|
|
5599
|
-
function classifyComparatorOperands(left, right, paramA, paramB, type
|
|
5525
|
+
function classifyComparatorOperands(left, right, paramA, paramB, type) {
|
|
5600
5526
|
const leftRef = classifySortOperand(left, paramA, paramB);
|
|
5601
5527
|
const rightRef = classifySortOperand(right, paramA, paramB);
|
|
5602
5528
|
if (!leftRef || !rightRef)
|
|
@@ -5609,15 +5535,89 @@ function classifyComparatorOperands(left, right, paramA, paramB, type, method, r
|
|
|
5609
5535
|
return null;
|
|
5610
5536
|
}
|
|
5611
5537
|
const direction = leftRef.param === "A" ? "asc" : "desc";
|
|
5612
|
-
return {
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5538
|
+
return { key: leftRef.key, type, direction };
|
|
5539
|
+
}
|
|
5540
|
+
function classifyTernaryComparator(node, paramA, paramB) {
|
|
5541
|
+
const cond = unwrapParens(node.condition);
|
|
5542
|
+
if (ts8.isBinaryExpression(cond) && (cond.operatorToken.kind === ts8.SyntaxKind.EqualsEqualsEqualsToken || cond.operatorToken.kind === ts8.SyntaxKind.EqualsEqualsToken) && sameKeyOperands(cond.left, cond.right, paramA, paramB) && numericSign(node.whenTrue) === 0) {
|
|
5543
|
+
const elseBranch = unwrapParens(node.whenFalse);
|
|
5544
|
+
if (ts8.isConditionalExpression(elseBranch)) {
|
|
5545
|
+
return classifyTernaryComparator(elseBranch, paramA, paramB);
|
|
5546
|
+
}
|
|
5547
|
+
return null;
|
|
5548
|
+
}
|
|
5549
|
+
if (!ts8.isBinaryExpression(cond))
|
|
5550
|
+
return null;
|
|
5551
|
+
const op = cond.operatorToken.kind;
|
|
5552
|
+
const isGreater = op === ts8.SyntaxKind.GreaterThanToken || op === ts8.SyntaxKind.GreaterThanEqualsToken;
|
|
5553
|
+
const isLess = op === ts8.SyntaxKind.LessThanToken || op === ts8.SyntaxKind.LessThanEqualsToken;
|
|
5554
|
+
if (!isGreater && !isLess)
|
|
5555
|
+
return null;
|
|
5556
|
+
const leftRef = classifySortOperand(cond.left, paramA, paramB);
|
|
5557
|
+
const rightRef = classifySortOperand(cond.right, paramA, paramB);
|
|
5558
|
+
if (!leftRef || !rightRef)
|
|
5559
|
+
return null;
|
|
5560
|
+
if (leftRef.param === rightRef.param)
|
|
5561
|
+
return null;
|
|
5562
|
+
if (leftRef.key.kind !== rightRef.key.kind)
|
|
5563
|
+
return null;
|
|
5564
|
+
if (leftRef.key.kind === "field" && rightRef.key.kind === "field" && leftRef.key.field !== rightRef.key.field) {
|
|
5565
|
+
return null;
|
|
5566
|
+
}
|
|
5567
|
+
const trueSign = numericSign(node.whenTrue);
|
|
5568
|
+
if (trueSign === null || trueSign === 0)
|
|
5569
|
+
return null;
|
|
5570
|
+
if (!isBoundedTernaryElse(node.whenFalse, leftRef.key, paramA, paramB))
|
|
5571
|
+
return null;
|
|
5572
|
+
const greaterForA = leftRef.param === "A" ? isGreater : !isGreater;
|
|
5573
|
+
const asc = greaterForA ? trueSign > 0 : trueSign < 0;
|
|
5574
|
+
return { key: leftRef.key, type: "auto", direction: asc ? "asc" : "desc" };
|
|
5575
|
+
}
|
|
5576
|
+
function sameKeyOperands(left, right, paramA, paramB) {
|
|
5577
|
+
const l = classifySortOperand(left, paramA, paramB);
|
|
5578
|
+
const r = classifySortOperand(right, paramA, paramB);
|
|
5579
|
+
if (!l || !r)
|
|
5580
|
+
return false;
|
|
5581
|
+
if (l.param === r.param)
|
|
5582
|
+
return false;
|
|
5583
|
+
if (l.key.kind !== r.key.kind)
|
|
5584
|
+
return false;
|
|
5585
|
+
if (l.key.kind === "field" && r.key.kind === "field" && l.key.field !== r.key.field)
|
|
5586
|
+
return false;
|
|
5587
|
+
return true;
|
|
5588
|
+
}
|
|
5589
|
+
function numericSign(expr) {
|
|
5590
|
+
const e = unwrapParens(expr);
|
|
5591
|
+
if (ts8.isPrefixUnaryExpression(e) && e.operator === ts8.SyntaxKind.MinusToken) {
|
|
5592
|
+
const inner = numericSign(e.operand);
|
|
5593
|
+
return inner === null ? null : -inner;
|
|
5594
|
+
}
|
|
5595
|
+
if (ts8.isNumericLiteral(e)) {
|
|
5596
|
+
const n = Number(e.text);
|
|
5597
|
+
if (Number.isNaN(n))
|
|
5598
|
+
return null;
|
|
5599
|
+
if (n === 0)
|
|
5600
|
+
return 0;
|
|
5601
|
+
return n > 0 ? 1 : -1;
|
|
5602
|
+
}
|
|
5603
|
+
return null;
|
|
5604
|
+
}
|
|
5605
|
+
function isBoundedTernaryElse(expr, key, paramA, paramB) {
|
|
5606
|
+
const e = unwrapParens(expr);
|
|
5607
|
+
if (numericSign(e) !== null)
|
|
5608
|
+
return true;
|
|
5609
|
+
if (ts8.isConditionalExpression(e)) {
|
|
5610
|
+
const nested = classifyTernaryComparator(e, paramA, paramB);
|
|
5611
|
+
return nested !== null && sortKeyEquals(nested.key, key);
|
|
5612
|
+
}
|
|
5613
|
+
return false;
|
|
5614
|
+
}
|
|
5615
|
+
function sortKeyEquals(a, b) {
|
|
5616
|
+
if (a.kind !== b.kind)
|
|
5617
|
+
return false;
|
|
5618
|
+
if (a.kind === "field" && b.kind === "field")
|
|
5619
|
+
return a.field === b.field;
|
|
5620
|
+
return true;
|
|
5621
5621
|
}
|
|
5622
5622
|
function classifySortOperand(expr, paramA, paramB) {
|
|
5623
5623
|
if (ts8.isIdentifier(expr)) {
|
|
@@ -7543,6 +7543,23 @@ function containsJsxInExpression(node) {
|
|
|
7543
7543
|
}
|
|
7544
7544
|
return ts11.forEachChild(node, containsJsxInExpression) ?? false;
|
|
7545
7545
|
}
|
|
7546
|
+
function callsJsxHelper(node, ctx) {
|
|
7547
|
+
let found = false;
|
|
7548
|
+
const visit2 = (n) => {
|
|
7549
|
+
if (found)
|
|
7550
|
+
return;
|
|
7551
|
+
if (ts11.isCallExpression(n) && ts11.isIdentifier(n.expression)) {
|
|
7552
|
+
const name = n.expression.text;
|
|
7553
|
+
if (ctx.analyzer.jsxFunctions.has(name) || ctx.analyzer.jsxMultiReturnFunctions.has(name)) {
|
|
7554
|
+
found = true;
|
|
7555
|
+
return;
|
|
7556
|
+
}
|
|
7557
|
+
}
|
|
7558
|
+
ts11.forEachChild(n, visit2);
|
|
7559
|
+
};
|
|
7560
|
+
visit2(node);
|
|
7561
|
+
return found;
|
|
7562
|
+
}
|
|
7546
7563
|
function containsAwaitExpression(node) {
|
|
7547
7564
|
if (ts11.isAwaitExpression(node))
|
|
7548
7565
|
return true;
|
|
@@ -7622,7 +7639,7 @@ function transformJsxExpression(expr, ctx, isClientOnly = false) {
|
|
|
7622
7639
|
if (node.operatorToken.kind === ts11.SyntaxKind.AmpersandAmpersandToken) {
|
|
7623
7640
|
return transformLogicalAnd(node, ctx);
|
|
7624
7641
|
}
|
|
7625
|
-
if ((node.operatorToken.kind === ts11.SyntaxKind.QuestionQuestionToken || node.operatorToken.kind === ts11.SyntaxKind.BarBarToken) && containsJsxInExpression(node.right)) {
|
|
7642
|
+
if ((node.operatorToken.kind === ts11.SyntaxKind.QuestionQuestionToken || node.operatorToken.kind === ts11.SyntaxKind.BarBarToken) && (containsJsxInExpression(node.right) || callsJsxHelper(node.right, ctx))) {
|
|
7626
7643
|
return transformNullishCoalescing(node, ctx);
|
|
7627
7644
|
}
|
|
7628
7645
|
return null;
|
|
@@ -8079,23 +8096,23 @@ function checkLoopKey(callback, ctx, isNested) {
|
|
|
8079
8096
|
}
|
|
8080
8097
|
while (ts11.isParenthesizedExpression(body))
|
|
8081
8098
|
body = body.expression;
|
|
8099
|
+
function checkJsxOperand(node) {
|
|
8100
|
+
let n = node;
|
|
8101
|
+
while (ts11.isParenthesizedExpression(n))
|
|
8102
|
+
n = n.expression;
|
|
8103
|
+
if (ts11.isJsxElement(n))
|
|
8104
|
+
checkOpening(n.openingElement);
|
|
8105
|
+
else if (ts11.isJsxSelfClosingElement(n))
|
|
8106
|
+
checkOpening(n);
|
|
8107
|
+
}
|
|
8082
8108
|
if (ts11.isConditionalExpression(body)) {
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
wf = wf.expression;
|
|
8091
|
-
if (ts11.isJsxElement(wt))
|
|
8092
|
-
checkOpening(wt.openingElement);
|
|
8093
|
-
else if (ts11.isJsxSelfClosingElement(wt))
|
|
8094
|
-
checkOpening(wt);
|
|
8095
|
-
if (ts11.isJsxElement(wf))
|
|
8096
|
-
checkOpening(wf.openingElement);
|
|
8097
|
-
else if (ts11.isJsxSelfClosingElement(wf))
|
|
8098
|
-
checkOpening(wf);
|
|
8109
|
+
checkJsxOperand(body.whenTrue);
|
|
8110
|
+
checkJsxOperand(body.whenFalse);
|
|
8111
|
+
return;
|
|
8112
|
+
}
|
|
8113
|
+
if (ts11.isBinaryExpression(body) && (body.operatorToken.kind === ts11.SyntaxKind.AmpersandAmpersandToken || body.operatorToken.kind === ts11.SyntaxKind.BarBarToken || body.operatorToken.kind === ts11.SyntaxKind.QuestionQuestionToken)) {
|
|
8114
|
+
checkJsxOperand(body.left);
|
|
8115
|
+
checkJsxOperand(body.right);
|
|
8099
8116
|
return;
|
|
8100
8117
|
}
|
|
8101
8118
|
if (ts11.isJsxElement(body)) {
|
|
@@ -8118,6 +8135,38 @@ function loopBodyIsMultiRoot(children) {
|
|
|
8118
8135
|
return false;
|
|
8119
8136
|
return loopBodyIsMultiRoot(only.children);
|
|
8120
8137
|
}
|
|
8138
|
+
function branchHasNoElement(node) {
|
|
8139
|
+
if (node.type === "element" || node.type === "component")
|
|
8140
|
+
return false;
|
|
8141
|
+
if (node.type === "conditional") {
|
|
8142
|
+
return branchHasNoElement(node.whenTrue) || branchHasNoElement(node.whenFalse);
|
|
8143
|
+
}
|
|
8144
|
+
if (node.type === "fragment") {
|
|
8145
|
+
const real = node.children.filter((c) => !(c.type === "text" && typeof c.value === "string" && !c.value.trim()));
|
|
8146
|
+
return real.length !== 1 || branchHasNoElement(real[0]);
|
|
8147
|
+
}
|
|
8148
|
+
return true;
|
|
8149
|
+
}
|
|
8150
|
+
function loopBodyItemConditional(children) {
|
|
8151
|
+
const real = children.filter((c) => !(c.type === "text" && typeof c.value === "string" && !c.value.trim()));
|
|
8152
|
+
if (real.length !== 1)
|
|
8153
|
+
return null;
|
|
8154
|
+
const only = real[0];
|
|
8155
|
+
if (only.type !== "conditional")
|
|
8156
|
+
return null;
|
|
8157
|
+
if (branchHasNoElement(only.whenTrue) || branchHasNoElement(only.whenFalse)) {
|
|
8158
|
+
return only;
|
|
8159
|
+
}
|
|
8160
|
+
return null;
|
|
8161
|
+
}
|
|
8162
|
+
function extractItemConditionalKey(cond) {
|
|
8163
|
+
const a = branchHasNoElement(cond.whenTrue) ? null : extractLoopKey(cond.whenTrue);
|
|
8164
|
+
const b = branchHasNoElement(cond.whenFalse) ? null : extractLoopKey(cond.whenFalse);
|
|
8165
|
+
if (a !== null && b !== null) {
|
|
8166
|
+
return normalizeKeyExpr(a) === normalizeKeyExpr(b) ? a : null;
|
|
8167
|
+
}
|
|
8168
|
+
return a ?? b;
|
|
8169
|
+
}
|
|
8121
8170
|
function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
8122
8171
|
const isNested = ctx.loopParams.size > 0;
|
|
8123
8172
|
const propAccess = node.expression;
|
|
@@ -8280,6 +8329,19 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
8280
8329
|
}
|
|
8281
8330
|
if (index)
|
|
8282
8331
|
ctx.loopParams.add(index);
|
|
8332
|
+
const tryTransformRenderableBody = (expr) => {
|
|
8333
|
+
if (!ts11.isBinaryExpression(expr))
|
|
8334
|
+
return;
|
|
8335
|
+
const op = expr.operatorToken.kind;
|
|
8336
|
+
if (op !== ts11.SyntaxKind.AmpersandAmpersandToken && op !== ts11.SyntaxKind.BarBarToken && op !== ts11.SyntaxKind.QuestionQuestionToken) {
|
|
8337
|
+
return;
|
|
8338
|
+
}
|
|
8339
|
+
if (!containsJsxInExpression(expr) && !callsJsxHelper(expr, ctx))
|
|
8340
|
+
return;
|
|
8341
|
+
const transformed = transformJsxExpression(expr, ctx, isClientOnly);
|
|
8342
|
+
if (transformed)
|
|
8343
|
+
children = [transformed];
|
|
8344
|
+
};
|
|
8283
8345
|
const body = callback.body;
|
|
8284
8346
|
if (ts11.isJsxElement(body) || ts11.isJsxSelfClosingElement(body) || ts11.isJsxFragment(body)) {
|
|
8285
8347
|
const transformed = transformNode(body, ctx);
|
|
@@ -8302,6 +8364,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
8302
8364
|
children = [transformConditional(inner, ctx)];
|
|
8303
8365
|
} else if (method === "flatMap" && ts11.isArrayLiteralExpression(inner)) {
|
|
8304
8366
|
children = transformArrayLiteralChildren(inner, ctx);
|
|
8367
|
+
} else {
|
|
8368
|
+
tryTransformRenderableBody(inner);
|
|
8305
8369
|
}
|
|
8306
8370
|
} else if (method === "flatMap" && ts11.isArrayLiteralExpression(body)) {
|
|
8307
8371
|
children = transformArrayLiteralChildren(body, ctx);
|
|
@@ -8350,6 +8414,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
8350
8414
|
if (method === "flatMap" && children.length === 0) {
|
|
8351
8415
|
flatMapCallback = buildFlatMapCallback(callback, body, ctx);
|
|
8352
8416
|
}
|
|
8417
|
+
} else {
|
|
8418
|
+
tryTransformRenderableBody(body);
|
|
8353
8419
|
}
|
|
8354
8420
|
if (paramBindings) {
|
|
8355
8421
|
for (const b of paramBindings)
|
|
@@ -8366,7 +8432,9 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
8366
8432
|
if (ts11.isArrowFunction(node.arguments[0]) && children.length > 0) {
|
|
8367
8433
|
checkLoopKey(node.arguments[0], ctx, isNested);
|
|
8368
8434
|
}
|
|
8369
|
-
const
|
|
8435
|
+
const itemConditional = children.length > 0 ? loopBodyItemConditional(children) : null;
|
|
8436
|
+
const bodyIsItemConditional = itemConditional !== null;
|
|
8437
|
+
const key = bodyIsItemConditional ? extractItemConditionalKey(itemConditional) : children.length > 0 ? extractLoopKey(children[0]) : null;
|
|
8370
8438
|
let childComponent;
|
|
8371
8439
|
if (children.length === 1 && children[0].type === "component") {
|
|
8372
8440
|
const comp = children[0];
|
|
@@ -8405,6 +8473,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
8405
8473
|
callsReactiveGetters: callsReactive || undefined,
|
|
8406
8474
|
hasFunctionCalls: hasCalls || undefined,
|
|
8407
8475
|
bodyIsMultiRoot: bodyIsMultiRoot || undefined,
|
|
8476
|
+
bodyIsItemConditional: bodyIsItemConditional || undefined,
|
|
8408
8477
|
childComponent,
|
|
8409
8478
|
nestedComponents,
|
|
8410
8479
|
filterPredicate,
|
|
@@ -9583,7 +9652,8 @@ function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings)
|
|
|
9583
9652
|
if (!valueStr)
|
|
9584
9653
|
continue;
|
|
9585
9654
|
const expanded = expandConstantForReactivity(valueStr, ctx, attr.freeIdentifiers);
|
|
9586
|
-
|
|
9655
|
+
const reactive = classifyReactivity(expanded.expr, ctx, loopParam, loopParamBindings, expanded.freeIds).kind !== "none" || attr.callsReactiveGetters || attr.hasFunctionCalls;
|
|
9656
|
+
if (!attr.clientOnly && !reactive)
|
|
9587
9657
|
continue;
|
|
9588
9658
|
attrs.push({
|
|
9589
9659
|
childSlotId: el.slotId,
|
|
@@ -9697,6 +9767,7 @@ function collectInnerLoops(nodes, siblingOffsets, outerLoopParam, ctx, options)
|
|
|
9697
9767
|
key: n.key,
|
|
9698
9768
|
markerId: n.markerId,
|
|
9699
9769
|
bodyIsMultiRoot: n.bodyIsMultiRoot,
|
|
9770
|
+
bodyIsItemConditional: n.bodyIsItemConditional,
|
|
9700
9771
|
iterationShape: n.iterationShape,
|
|
9701
9772
|
containerSlotId: scope.parentSlotId,
|
|
9702
9773
|
template,
|
|
@@ -9911,6 +9982,7 @@ function collectElements(node, ctx, siblingOffsets, insideConditional = false) {
|
|
|
9911
9982
|
key: l.key,
|
|
9912
9983
|
markerId: l.markerId,
|
|
9913
9984
|
bodyIsMultiRoot: l.bodyIsMultiRoot,
|
|
9985
|
+
bodyIsItemConditional: l.bodyIsItemConditional,
|
|
9914
9986
|
iterationShape: l.iterationShape,
|
|
9915
9987
|
template,
|
|
9916
9988
|
staticItemTemplate,
|
|
@@ -10106,6 +10178,7 @@ function collectBranchLoops(node, ctx, siblingOffsets) {
|
|
|
10106
10178
|
key: n.key,
|
|
10107
10179
|
markerId: n.markerId,
|
|
10108
10180
|
bodyIsMultiRoot: n.bodyIsMultiRoot,
|
|
10181
|
+
bodyIsItemConditional: n.bodyIsItemConditional,
|
|
10109
10182
|
iterationShape: n.iterationShape,
|
|
10110
10183
|
template: childTemplate,
|
|
10111
10184
|
containerSlotId: containerSlot,
|
|
@@ -10672,6 +10745,7 @@ var RUNTIME_IMPORT_CANDIDATES = [
|
|
|
10672
10745
|
"getLoopChildren",
|
|
10673
10746
|
"getLoopNodes",
|
|
10674
10747
|
"mapArray",
|
|
10748
|
+
"mapArrayAnchored",
|
|
10675
10749
|
"createDisposableEffect",
|
|
10676
10750
|
"createComponent",
|
|
10677
10751
|
"renderChild",
|
|
@@ -10695,7 +10769,8 @@ var RUNTIME_IMPORT_CANDIDATES = [
|
|
|
10695
10769
|
"qsaChildScopes",
|
|
10696
10770
|
"upsertChildItem",
|
|
10697
10771
|
"__slot",
|
|
10698
|
-
"__bfSlot"
|
|
10772
|
+
"__bfSlot",
|
|
10773
|
+
"__bfText"
|
|
10699
10774
|
];
|
|
10700
10775
|
var RUNTIME_MODULE = "@barefootjs/client/runtime";
|
|
10701
10776
|
var IMPORT_PLACEHOLDER = "/* __BAREFOOTJS_DOM_IMPORTS__ */";
|
|
@@ -12691,10 +12766,11 @@ function emitInnerLoopNested(lines, plan) {
|
|
|
12691
12766
|
for (const stmt of innerPreludeStatements) {
|
|
12692
12767
|
lines.push(` ${stmt}`);
|
|
12693
12768
|
}
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
-
lines.push(`
|
|
12697
|
-
|
|
12769
|
+
comps.forEach((comp, i) => {
|
|
12770
|
+
const compElVar = comps.length > 1 ? `__compEl${i}` : "__compEl";
|
|
12771
|
+
lines.push(` const ${compElVar} = qsaChildScope(__innerEl, ${comp.selector})`);
|
|
12772
|
+
lines.push(` if (${compElVar}) initChild('${nameForRegistryRef(comp.componentName)}', ${compElVar}, ${comp.propsExpr})`);
|
|
12773
|
+
});
|
|
12698
12774
|
lines.push(` })`);
|
|
12699
12775
|
lines.push(` })`);
|
|
12700
12776
|
lines.push(` }`);
|
|
@@ -13516,17 +13592,21 @@ function emitDynamicTextUpdates(lines, ctx) {
|
|
|
13516
13592
|
const conditionalElems = elems.filter((e) => e.insideConditional);
|
|
13517
13593
|
const normalElems = elems.filter((e) => !e.insideConditional);
|
|
13518
13594
|
if (normalElems.length > 0 || conditionalElems.length > 0) {
|
|
13595
|
+
for (const elem of normalElems) {
|
|
13596
|
+
const v = varSlotId(elem.slotId);
|
|
13597
|
+
lines.push(` let __anchor_${v} = _${v}`);
|
|
13598
|
+
}
|
|
13519
13599
|
lines.push(` createEffect(() => {`);
|
|
13520
13600
|
if (normalElems.length > 0) {
|
|
13521
13601
|
lines.push(` const __val = ${expr}`);
|
|
13522
13602
|
for (const elem of normalElems) {
|
|
13523
13603
|
const v = varSlotId(elem.slotId);
|
|
13524
|
-
lines.push(`
|
|
13604
|
+
lines.push(` __anchor_${v} = __bfText(__anchor_${v}, __val)`);
|
|
13525
13605
|
}
|
|
13526
13606
|
for (const elem of conditionalElems) {
|
|
13527
13607
|
const v = varSlotId(elem.slotId);
|
|
13528
13608
|
lines.push(` const [__el_${v}] = $t(__scope, '${elem.slotId}')`);
|
|
13529
|
-
lines.push(`
|
|
13609
|
+
lines.push(` __bfText(__el_${v}, __val)`);
|
|
13530
13610
|
}
|
|
13531
13611
|
} else {
|
|
13532
13612
|
lines.push(` let __val`);
|
|
@@ -13534,7 +13614,7 @@ function emitDynamicTextUpdates(lines, ctx) {
|
|
|
13534
13614
|
for (const elem of conditionalElems) {
|
|
13535
13615
|
const v = varSlotId(elem.slotId);
|
|
13536
13616
|
lines.push(` const [__el_${v}] = $t(__scope, '${elem.slotId}')`);
|
|
13537
|
-
lines.push(`
|
|
13617
|
+
lines.push(` __bfText(__el_${v}, __val)`);
|
|
13538
13618
|
}
|
|
13539
13619
|
}
|
|
13540
13620
|
lines.push(` })`);
|
|
@@ -14030,8 +14110,14 @@ function stringifyPlainLoop(lines, plan, topIndent = " ") {
|
|
|
14030
14110
|
template,
|
|
14031
14111
|
reactiveEffects,
|
|
14032
14112
|
childRefs,
|
|
14033
|
-
bodyIsMultiRoot
|
|
14113
|
+
bodyIsMultiRoot,
|
|
14114
|
+
anchored,
|
|
14115
|
+
anchorKeyExpr
|
|
14034
14116
|
} = plan;
|
|
14117
|
+
if (anchored) {
|
|
14118
|
+
stringifyAnchoredLoop(lines, plan, topIndent, anchorKeyExpr);
|
|
14119
|
+
return;
|
|
14120
|
+
}
|
|
14035
14121
|
if (reactiveEffects === null && !bodyIsMultiRoot && childRefs.length === 0) {
|
|
14036
14122
|
const unwrapInline = paramUnwrap ? `${paramUnwrap} ` : "";
|
|
14037
14123
|
const preamble = mapPreambleWrapped ? `${mapPreambleWrapped}; ` : "";
|
|
@@ -14058,6 +14144,41 @@ function stringifyPlainLoop(lines, plan, topIndent = " ") {
|
|
|
14058
14144
|
lines.push(`${bodyIndent}return __el`);
|
|
14059
14145
|
lines.push(`${topIndent}}, '${markerId}')`);
|
|
14060
14146
|
}
|
|
14147
|
+
function stringifyAnchoredLoop(lines, plan, topIndent, anchorKeyExpr) {
|
|
14148
|
+
const {
|
|
14149
|
+
containerVar,
|
|
14150
|
+
markerId,
|
|
14151
|
+
arrayExpr,
|
|
14152
|
+
keyFn,
|
|
14153
|
+
paramHead,
|
|
14154
|
+
paramUnwrap,
|
|
14155
|
+
indexParam,
|
|
14156
|
+
mapPreambleWrapped,
|
|
14157
|
+
reactiveEffects
|
|
14158
|
+
} = plan;
|
|
14159
|
+
const condSlot = reactiveEffects?.conditionals[0]?.slotId ?? null;
|
|
14160
|
+
lines.push(`${topIndent}mapArrayAnchored(() => ${arrayExpr}, ${containerVar}, ${keyFn}, (${paramHead}, ${indexParam}, __existing) => {`);
|
|
14161
|
+
const bodyIndent = topIndent + " ";
|
|
14162
|
+
if (paramUnwrap)
|
|
14163
|
+
lines.push(`${bodyIndent}${paramUnwrap}`);
|
|
14164
|
+
if (mapPreambleWrapped)
|
|
14165
|
+
lines.push(`${bodyIndent}${mapPreambleWrapped}`);
|
|
14166
|
+
lines.push(`${bodyIndent}const __anchor = __existing ?? document.createComment(\`bf-loop-i:\${${anchorKeyExpr}}\`)`);
|
|
14167
|
+
lines.push(`${bodyIndent}let __frag = null`);
|
|
14168
|
+
lines.push(`${bodyIndent}if (!__existing) {`);
|
|
14169
|
+
lines.push(`${bodyIndent} __frag = document.createDocumentFragment()`);
|
|
14170
|
+
lines.push(`${bodyIndent} __frag.appendChild(__anchor)`);
|
|
14171
|
+
if (condSlot) {
|
|
14172
|
+
lines.push(`${bodyIndent} __frag.appendChild(document.createComment('bf-cond-start:${condSlot}'))`);
|
|
14173
|
+
lines.push(`${bodyIndent} __frag.appendChild(document.createComment('bf-cond-end:${condSlot}'))`);
|
|
14174
|
+
}
|
|
14175
|
+
lines.push(`${bodyIndent}}`);
|
|
14176
|
+
if (reactiveEffects !== null) {
|
|
14177
|
+
stringifyReactiveEffects(lines, reactiveEffects, { indent: bodyIndent, elVar: "__anchor", bodyIsMultiRoot: false });
|
|
14178
|
+
}
|
|
14179
|
+
lines.push(`${bodyIndent}return __frag ?? __anchor`);
|
|
14180
|
+
lines.push(`${topIndent}}, '${markerId}')`);
|
|
14181
|
+
}
|
|
14061
14182
|
function stringifyStaticLoop(lines, plan) {
|
|
14062
14183
|
const { containerVar, arrayExpr, param, indexParam, childIndexExpr, attrsBySlot, texts, childRefs, csrMaterialize } = plan;
|
|
14063
14184
|
const hasAttrs = attrsBySlot.length > 0;
|
|
@@ -14577,10 +14698,10 @@ function emitArmBody2(lines, body, mode, indent) {
|
|
|
14577
14698
|
}
|
|
14578
14699
|
for (const te of body.textEffects) {
|
|
14579
14700
|
const v = varSlotId(te.slotId);
|
|
14580
|
-
lines.push(`${indent}
|
|
14701
|
+
lines.push(`${indent}let __anchor_${v} = $t(__branchScope, '${te.slotId}')[0]`);
|
|
14581
14702
|
lines.push(`${indent}__disposers.push(createDisposableEffect(() => {`);
|
|
14582
14703
|
lines.push(`${indent} const __val = ${te.expression}`);
|
|
14583
|
-
lines.push(`${indent}
|
|
14704
|
+
lines.push(`${indent} __anchor_${v} = __bfText(__anchor_${v}, __val)`);
|
|
14584
14705
|
lines.push(`${indent}}))`);
|
|
14585
14706
|
}
|
|
14586
14707
|
if (body.loops.length > 0) {
|
|
@@ -14653,6 +14774,9 @@ function buildComponentLoopPlan(elem) {
|
|
|
14653
14774
|
|
|
14654
14775
|
// src/ir-to-client-js/control-flow/plan/build-loop.ts
|
|
14655
14776
|
function buildLoopPlan(elem, opts) {
|
|
14777
|
+
if (elem.bodyIsItemConditional) {
|
|
14778
|
+
return buildPlainLoopPlan(elem);
|
|
14779
|
+
}
|
|
14656
14780
|
if (elem.isStaticArray) {
|
|
14657
14781
|
return buildStaticLoopPlan(elem, opts.unsafeLocalNames);
|
|
14658
14782
|
}
|
|
@@ -14682,7 +14806,9 @@ function buildPlainLoopPlan(elem) {
|
|
|
14682
14806
|
template: elem.template,
|
|
14683
14807
|
reactiveEffects: hasReactive2 ? buildLoopReactiveEffectsPlan(elem) : null,
|
|
14684
14808
|
childRefs: buildChildRefBindings(elem.bindings.refs, elem.param, elem.paramBindings),
|
|
14685
|
-
bodyIsMultiRoot: elem.bodyIsMultiRoot ?? false
|
|
14809
|
+
bodyIsMultiRoot: elem.bodyIsMultiRoot ?? false,
|
|
14810
|
+
anchored: elem.bodyIsItemConditional ?? false,
|
|
14811
|
+
anchorKeyExpr: elem.key ? wrap(elem.key) : elem.index || "__idx"
|
|
14686
14812
|
};
|
|
14687
14813
|
}
|
|
14688
14814
|
function buildStaticLoopPlan(elem, unsafeLocalNames) {
|
|
@@ -15672,18 +15798,25 @@ function runSinglePass(source, filePath, startingCounter) {
|
|
|
15672
15798
|
}
|
|
15673
15799
|
function visit3(node) {
|
|
15674
15800
|
if (ts15.isJsxAttribute(node) && node.initializer && ts15.isJsxExpression(node.initializer) && node.initializer.expression) {
|
|
15675
|
-
|
|
15676
|
-
|
|
15677
|
-
expr = expr.expression;
|
|
15678
|
-
if (ts15.isArrowFunction(expr) && arrowBodyContainsJsx(expr)) {
|
|
15679
|
-
const handled = handleInlineArrow(expr);
|
|
15680
|
-
if (handled) {
|
|
15681
|
-
return;
|
|
15682
|
-
}
|
|
15801
|
+
if (tryHandleArrowValue(node.initializer.expression)) {
|
|
15802
|
+
return;
|
|
15683
15803
|
}
|
|
15684
15804
|
}
|
|
15805
|
+
if (ts15.isPropertyAssignment(node) && node.initializer) {
|
|
15806
|
+
if (tryHandleArrowValue(node.initializer))
|
|
15807
|
+
return;
|
|
15808
|
+
}
|
|
15685
15809
|
ts15.forEachChild(node, visit3);
|
|
15686
15810
|
}
|
|
15811
|
+
function tryHandleArrowValue(initializer) {
|
|
15812
|
+
let expr = initializer;
|
|
15813
|
+
while (ts15.isParenthesizedExpression(expr))
|
|
15814
|
+
expr = expr.expression;
|
|
15815
|
+
if (ts15.isArrowFunction(expr) && arrowBodyContainsJsx(expr)) {
|
|
15816
|
+
return handleInlineArrow(expr);
|
|
15817
|
+
}
|
|
15818
|
+
return false;
|
|
15819
|
+
}
|
|
15687
15820
|
function handleInlineArrow(arrow) {
|
|
15688
15821
|
const paramNames = collectArrowParamNames(arrow);
|
|
15689
15822
|
const free = collectFreeIdentifiers(arrow);
|
|
@@ -18365,6 +18498,7 @@ export {
|
|
|
18365
18498
|
rewriteImportsForTemplate,
|
|
18366
18499
|
resolveSetters,
|
|
18367
18500
|
resetCompilerCounters,
|
|
18501
|
+
renderImportMapHtml,
|
|
18368
18502
|
parseExpression,
|
|
18369
18503
|
parseBlockBody,
|
|
18370
18504
|
needsTypeBasedDetection,
|