@barefootjs/vite 0.31.2 → 0.31.4
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/index.js +224 -103
- package/package.json +6 -6
- package/src/__tests__/dynamic-import-rewrite.test.ts +92 -0
package/dist/index.js
CHANGED
|
@@ -1655,6 +1655,24 @@ function templatePartsToJsExpr(parts, opts) {
|
|
|
1655
1655
|
return result;
|
|
1656
1656
|
}
|
|
1657
1657
|
|
|
1658
|
+
// ../jsx/src/identifier-pattern.ts
|
|
1659
|
+
function withUnicodeFlag(flags) {
|
|
1660
|
+
return flags.includes("u") ? flags : `${flags}u`;
|
|
1661
|
+
}
|
|
1662
|
+
function escapeIdentifierForRegex(name) {
|
|
1663
|
+
return name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1664
|
+
}
|
|
1665
|
+
var ID_BOUNDARY_BEFORE = "(?<![\\p{ID_Continue}$])";
|
|
1666
|
+
var ID_BOUNDARY_AFTER = "(?![\\p{ID_Continue}$])";
|
|
1667
|
+
function identifierPattern(name, flags = "") {
|
|
1668
|
+
const esc = escapeIdentifierForRegex(name);
|
|
1669
|
+
return new RegExp(`${ID_BOUNDARY_BEFORE}${esc}${ID_BOUNDARY_AFTER}`, withUnicodeFlag(flags));
|
|
1670
|
+
}
|
|
1671
|
+
function identifierCallPattern(name, flags = "") {
|
|
1672
|
+
const esc = escapeIdentifierForRegex(name);
|
|
1673
|
+
return new RegExp(`${ID_BOUNDARY_BEFORE}${esc}\\s*\\(`, withUnicodeFlag(flags));
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1658
1676
|
// ../jsx/src/scanner/js-scanner.ts
|
|
1659
1677
|
import ts2 from "typescript";
|
|
1660
1678
|
function* iterateJsTokens(text, start = 0, end = text.length) {
|
|
@@ -2227,9 +2245,6 @@ function inferDefaultValue(type) {
|
|
|
2227
2245
|
return "{}";
|
|
2228
2246
|
return "undefined";
|
|
2229
2247
|
}
|
|
2230
|
-
function escapeRegExp(s) {
|
|
2231
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2232
|
-
}
|
|
2233
2248
|
function freeIdsFromRefs(refs) {
|
|
2234
2249
|
const out = new Set;
|
|
2235
2250
|
if (!refs)
|
|
@@ -2357,16 +2372,16 @@ function wrapLoopParamAsAccessor(expr, paramName, bindings) {
|
|
|
2357
2372
|
if (bindings && bindings.length > 0) {
|
|
2358
2373
|
return rewriteLoopBindingRefs(expr, bindings, "__bfItem()");
|
|
2359
2374
|
}
|
|
2360
|
-
const re = new RegExp(
|
|
2361
|
-
return replaceInExprContexts(expr, re, `${paramName}()`);
|
|
2375
|
+
const re = new RegExp(`${ID_BOUNDARY_BEFORE}${escapeIdentifierForRegex(paramName)}(?!\\s*\\()(?!-)${ID_BOUNDARY_AFTER}`, "gu");
|
|
2376
|
+
return replaceInExprContexts(expr, re, () => `${paramName}()`);
|
|
2362
2377
|
}
|
|
2363
2378
|
function rewriteLoopBindingRefs(expr, bindings, accessor) {
|
|
2364
2379
|
const byName = new Map;
|
|
2365
2380
|
for (const b of bindings)
|
|
2366
2381
|
byName.set(b.name, b);
|
|
2367
2382
|
const preprocessed = expandShorthandBindings(expr, new Set(byName.keys()));
|
|
2368
|
-
const alt = bindings.map((b) =>
|
|
2369
|
-
const re = new RegExp(
|
|
2383
|
+
const alt = bindings.map((b) => escapeIdentifierForRegex(b.name)).join("|");
|
|
2384
|
+
const re = new RegExp(`${ID_BOUNDARY_BEFORE}(${alt})${ID_BOUNDARY_AFTER}`, "gu");
|
|
2370
2385
|
return replaceInExprContexts(preprocessed, re, (_m, name) => renderLoopBindingAccess(byName.get(name), accessor));
|
|
2371
2386
|
}
|
|
2372
2387
|
function expandShorthandBindings(expr, bindingNames) {
|
|
@@ -2633,7 +2648,7 @@ function stopAt(...kinds) {
|
|
|
2633
2648
|
|
|
2634
2649
|
// ../jsx/src/ir-to-client-js/csr-substitute.ts
|
|
2635
2650
|
import ts4 from "typescript";
|
|
2636
|
-
function csrSubstitute(value, env) {
|
|
2651
|
+
function csrSubstitute(value, env, enclosingScope) {
|
|
2637
2652
|
if (!value || value.trim().length === 0) {
|
|
2638
2653
|
return { rewritten: value, freeIdentifiers: new Set };
|
|
2639
2654
|
}
|
|
@@ -2641,7 +2656,7 @@ function csrSubstitute(value, env) {
|
|
|
2641
2656
|
let current = value;
|
|
2642
2657
|
let lastFreeIdentifiers = new Set;
|
|
2643
2658
|
for (let i = 0;i < maxIter; i++) {
|
|
2644
|
-
const step = csrSubstituteOnce(current, env);
|
|
2659
|
+
const step = csrSubstituteOnce(current, env, enclosingScope);
|
|
2645
2660
|
lastFreeIdentifiers = step.freeIdentifiers;
|
|
2646
2661
|
if (step.rewritten === current)
|
|
2647
2662
|
break;
|
|
@@ -2649,7 +2664,7 @@ function csrSubstitute(value, env) {
|
|
|
2649
2664
|
}
|
|
2650
2665
|
return { rewritten: current, freeIdentifiers: lastFreeIdentifiers };
|
|
2651
2666
|
}
|
|
2652
|
-
function csrSubstituteOnce(value, env) {
|
|
2667
|
+
function csrSubstituteOnce(value, env, enclosingScope) {
|
|
2653
2668
|
if (!value || value.trim().length === 0) {
|
|
2654
2669
|
return { rewritten: value, freeIdentifiers: new Set };
|
|
2655
2670
|
}
|
|
@@ -2667,7 +2682,7 @@ function csrSubstituteOnce(value, env) {
|
|
|
2667
2682
|
if (boundStack[i].has(name))
|
|
2668
2683
|
return true;
|
|
2669
2684
|
}
|
|
2670
|
-
return false;
|
|
2685
|
+
return enclosingScope?.isBound(name) ?? false;
|
|
2671
2686
|
};
|
|
2672
2687
|
const recordSubstitution = (start, end, sub) => {
|
|
2673
2688
|
splices.push({ start: start - OFFSET, end: end - OFFSET, text: `(${sub.replacement})` });
|
|
@@ -2852,6 +2867,83 @@ function derivesScopeFromSlot(comp) {
|
|
|
2852
2867
|
return comp.slotId != null && comp.loopItemRoot !== true;
|
|
2853
2868
|
}
|
|
2854
2869
|
|
|
2870
|
+
// ../jsx/src/scope/binding-scope.ts
|
|
2871
|
+
class BindingScope {
|
|
2872
|
+
frames;
|
|
2873
|
+
static EMPTY = new BindingScope([]);
|
|
2874
|
+
constructor(frames) {
|
|
2875
|
+
this.frames = frames;
|
|
2876
|
+
}
|
|
2877
|
+
enterLoopRow(loop) {
|
|
2878
|
+
const bindings = new Map;
|
|
2879
|
+
if (loop.paramBindings && loop.paramBindings.length > 0) {
|
|
2880
|
+
for (const b of loop.paramBindings)
|
|
2881
|
+
bindings.set(b.name, { source: "destructure" });
|
|
2882
|
+
} else {
|
|
2883
|
+
bindings.set(loop.param, { source: "item" });
|
|
2884
|
+
}
|
|
2885
|
+
if (loop.index != null)
|
|
2886
|
+
bindings.set(loop.index, { source: "index" });
|
|
2887
|
+
for (const name of loop.preamble?.declaredNames ?? [])
|
|
2888
|
+
bindings.set(name, { source: "preamble" });
|
|
2889
|
+
const frame = { kind: "loop-row", bindings };
|
|
2890
|
+
return new BindingScope([frame, ...this.frames]);
|
|
2891
|
+
}
|
|
2892
|
+
enterCallback(params) {
|
|
2893
|
+
const bindings = new Map;
|
|
2894
|
+
for (const name of params)
|
|
2895
|
+
bindings.set(name, { source: "param" });
|
|
2896
|
+
const frame = { kind: "callback", bindings };
|
|
2897
|
+
return new BindingScope([frame, ...this.frames]);
|
|
2898
|
+
}
|
|
2899
|
+
isBound(name) {
|
|
2900
|
+
for (const frame of this.frames) {
|
|
2901
|
+
if (frame.bindings.has(name))
|
|
2902
|
+
return true;
|
|
2903
|
+
}
|
|
2904
|
+
return false;
|
|
2905
|
+
}
|
|
2906
|
+
lookup(name) {
|
|
2907
|
+
for (let depth = 0;depth < this.frames.length; depth++) {
|
|
2908
|
+
const frame = this.frames[depth];
|
|
2909
|
+
const binding = frame.bindings.get(name);
|
|
2910
|
+
if (binding)
|
|
2911
|
+
return { depth, frame, binding };
|
|
2912
|
+
}
|
|
2913
|
+
return null;
|
|
2914
|
+
}
|
|
2915
|
+
boundNames() {
|
|
2916
|
+
if (this.boundNamesCache)
|
|
2917
|
+
return this.boundNamesCache;
|
|
2918
|
+
const names = new Set;
|
|
2919
|
+
for (const frame of this.frames) {
|
|
2920
|
+
for (const name of frame.bindings.keys())
|
|
2921
|
+
names.add(name);
|
|
2922
|
+
}
|
|
2923
|
+
this.boundNamesCache = names;
|
|
2924
|
+
return names;
|
|
2925
|
+
}
|
|
2926
|
+
boundNamesCache;
|
|
2927
|
+
valueBoundNamesCache;
|
|
2928
|
+
valueBoundNames() {
|
|
2929
|
+
if (this.valueBoundNamesCache)
|
|
2930
|
+
return this.valueBoundNamesCache;
|
|
2931
|
+
const names = new Set;
|
|
2932
|
+
for (const frame of this.frames) {
|
|
2933
|
+
for (const [name, binding] of frame.bindings) {
|
|
2934
|
+
if (binding.source === "item" || binding.source === "index" || binding.source === "destructure") {
|
|
2935
|
+
names.add(name);
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
this.valueBoundNamesCache = names;
|
|
2940
|
+
return names;
|
|
2941
|
+
}
|
|
2942
|
+
asShadowPredicate() {
|
|
2943
|
+
return (name) => this.isBound(name);
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
|
|
2855
2947
|
// ../jsx/src/ir-to-client-js/html-template.ts
|
|
2856
2948
|
function createStringProtector() {
|
|
2857
2949
|
const strings = [];
|
|
@@ -4077,7 +4169,7 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
4077
4169
|
const source = templateExpr ?? expr;
|
|
4078
4170
|
if (!source)
|
|
4079
4171
|
return source;
|
|
4080
|
-
const { rewritten, freeIdentifiers: freeIdentifiers2 } = csrSubstitute(source, env);
|
|
4172
|
+
const { rewritten, freeIdentifiers: freeIdentifiers2 } = csrSubstitute(source, env, opts.scope);
|
|
4081
4173
|
if (unsafeLocalNames && unsafeLocalNames.size > 0 && setIntersects(freeIdentifiers2, unsafeLocalNames)) {
|
|
4082
4174
|
return UNSAFE_TEMPLATE_EXPR;
|
|
4083
4175
|
}
|
|
@@ -4219,15 +4311,8 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
4219
4311
|
return `\${renderChild('${nameForRegistryRef(node.name)}', ${propsExpr}${keyArg || (slotArg ? ", undefined" : "")}${slotArg})}`;
|
|
4220
4312
|
}
|
|
4221
4313
|
case "loop": {
|
|
4222
|
-
const
|
|
4223
|
-
|
|
4224
|
-
for (const b of node.paramBindings)
|
|
4225
|
-
boundHere.add(b.name);
|
|
4226
|
-
} else if (!node.param.startsWith("[") && !node.param.startsWith("{")) {
|
|
4227
|
-
boundHere.add(node.param);
|
|
4228
|
-
}
|
|
4229
|
-
if (node.index)
|
|
4230
|
-
boundHere.add(node.index);
|
|
4314
|
+
const childScope = (opts.scope ?? BindingScope.EMPTY).enterLoopRow(node);
|
|
4315
|
+
const boundHere = childScope.boundNames();
|
|
4231
4316
|
const childEnv = {
|
|
4232
4317
|
...env,
|
|
4233
4318
|
substitutions: new Map([...env.substitutions].filter(([name]) => !boundHere.has(name)))
|
|
@@ -4236,7 +4321,7 @@ function generateCsrTemplateWithOpts(node, opts) {
|
|
|
4236
4321
|
...opts,
|
|
4237
4322
|
loopDepth: loopDepth + 1,
|
|
4238
4323
|
inHoistedChildren: false,
|
|
4239
|
-
|
|
4324
|
+
scope: childScope,
|
|
4240
4325
|
csrEnv: childEnv
|
|
4241
4326
|
});
|
|
4242
4327
|
let childTemplate = node.children.map(recurseInLoopBody).join("");
|
|
@@ -5439,7 +5524,8 @@ function visit(node, ctx, targetComponentName, namedExports) {
|
|
|
5439
5524
|
if (!ctx.componentNode) {
|
|
5440
5525
|
collectAmbientGlobals(node, ctx);
|
|
5441
5526
|
}
|
|
5442
|
-
|
|
5527
|
+
const isDeclareStatement = ts9.isVariableStatement(node) && (node.modifiers?.some((m) => m.kind === ts9.SyntaxKind.DeclareKeyword) ?? false);
|
|
5528
|
+
if (ts9.isVariableStatement(node) && !ctx.componentNode && !isDeclareStatement) {
|
|
5443
5529
|
const isExported = node.modifiers?.some((m) => m.kind === ts9.SyntaxKind.ExportKeyword) ?? false;
|
|
5444
5530
|
const isLet = (node.declarationList.flags & ts9.NodeFlags.Let) !== 0;
|
|
5445
5531
|
const isModuleClientDirective = hasLeadingClientDirectiveOnStatement(node, ctx.sourceFile);
|
|
@@ -5452,7 +5538,7 @@ function visit(node, ctx, targetComponentName, namedExports) {
|
|
|
5452
5538
|
}
|
|
5453
5539
|
continue;
|
|
5454
5540
|
}
|
|
5455
|
-
if (ts9.isIdentifier(decl.name) && decl.initializer && !isArrowComponentFunction(decl)) {
|
|
5541
|
+
if (ts9.isIdentifier(decl.name) && (decl.initializer || isLet) && !isArrowComponentFunction(decl)) {
|
|
5456
5542
|
collectConstant(decl, ctx, true, isLet ? "let" : "const", isExported);
|
|
5457
5543
|
}
|
|
5458
5544
|
}
|
|
@@ -7023,6 +7109,7 @@ function collectConstant(node, ctx, _isModule, declarationKind = "const", isExpo
|
|
|
7023
7109
|
value,
|
|
7024
7110
|
parsed,
|
|
7025
7111
|
typedValue: typedValue !== value ? typedValue : undefined,
|
|
7112
|
+
typeAnnotation: node.type ? node.type.getText(ctx.sourceFile) : undefined,
|
|
7026
7113
|
valueBranches,
|
|
7027
7114
|
declarationKind,
|
|
7028
7115
|
isExported,
|
|
@@ -8752,7 +8839,7 @@ function findReachableNames(primaryRefs, declarations) {
|
|
|
8752
8839
|
const reachable = new Set;
|
|
8753
8840
|
const queue = [];
|
|
8754
8841
|
for (const name of allNames) {
|
|
8755
|
-
if (
|
|
8842
|
+
if (identifierPattern(name).test(primaryRefs)) {
|
|
8756
8843
|
reachable.add(name);
|
|
8757
8844
|
queue.push(name);
|
|
8758
8845
|
}
|
|
@@ -8761,7 +8848,7 @@ function findReachableNames(primaryRefs, declarations) {
|
|
|
8761
8848
|
const current = queue.shift();
|
|
8762
8849
|
const body = bodyMap.get(current) || "";
|
|
8763
8850
|
for (const name of allNames) {
|
|
8764
|
-
if (!reachable.has(name) &&
|
|
8851
|
+
if (!reachable.has(name) && identifierPattern(name).test(body)) {
|
|
8765
8852
|
reachable.add(name);
|
|
8766
8853
|
queue.push(name);
|
|
8767
8854
|
}
|
|
@@ -9607,8 +9694,9 @@ function rewriteBarePropRefs2(text, expr, ctx) {
|
|
|
9607
9694
|
let propNames = getDestructuredPropNames(ctx);
|
|
9608
9695
|
if (!propNames)
|
|
9609
9696
|
return dateLowered === text ? undefined : dateLowered;
|
|
9610
|
-
|
|
9611
|
-
|
|
9697
|
+
const shadowingNames = ctx.scope.boundNames();
|
|
9698
|
+
if (shadowingNames.size > 0) {
|
|
9699
|
+
const filtered = new Set([...propNames].filter((n) => !shadowingNames.has(n)));
|
|
9612
9700
|
if (filtered.size === 0)
|
|
9613
9701
|
return dateLowered === text ? undefined : dateLowered;
|
|
9614
9702
|
propNames = filtered;
|
|
@@ -9684,22 +9772,22 @@ function createTransformContext(analyzer) {
|
|
|
9684
9772
|
spreadIdCounter: 0,
|
|
9685
9773
|
isRoot: true,
|
|
9686
9774
|
insideComponentChildren: false,
|
|
9687
|
-
|
|
9775
|
+
scope: BindingScope.EMPTY,
|
|
9688
9776
|
loopDepth: 0,
|
|
9689
9777
|
patterns: {
|
|
9690
9778
|
signals: analyzer.signals.map((s) => ({
|
|
9691
9779
|
getter: s.getter,
|
|
9692
|
-
pattern:
|
|
9780
|
+
pattern: identifierCallPattern(s.getter)
|
|
9693
9781
|
})),
|
|
9694
9782
|
memos: analyzer.memos.map((m) => ({
|
|
9695
9783
|
name: m.name,
|
|
9696
|
-
pattern:
|
|
9784
|
+
pattern: identifierCallPattern(m.name)
|
|
9697
9785
|
})),
|
|
9698
|
-
props: analyzer.propsParams.filter((p) => p.name !== "children").map((p) => ({ name: p.name, pattern:
|
|
9786
|
+
props: analyzer.propsParams.filter((p) => p.name !== "children").map((p) => ({ name: p.name, pattern: identifierPattern(p.name) })),
|
|
9699
9787
|
constants: analyzer.localConstants.map((c) => ({
|
|
9700
9788
|
name: c.name,
|
|
9701
9789
|
value: c.value,
|
|
9702
|
-
pattern:
|
|
9790
|
+
pattern: identifierPattern(c.name)
|
|
9703
9791
|
}))
|
|
9704
9792
|
},
|
|
9705
9793
|
getJS(node) {
|
|
@@ -9761,7 +9849,8 @@ function generateSpreadSlotId(ctx) {
|
|
|
9761
9849
|
return `Spread_${ctx.spreadIdCounter++}`;
|
|
9762
9850
|
}
|
|
9763
9851
|
function makeBindingEnv(ctx) {
|
|
9764
|
-
const
|
|
9852
|
+
const boundNames = ctx.scope.valueBoundNames();
|
|
9853
|
+
const loopKey = boundNames.size === 0 ? "" : Array.from(boundNames).sort().join("\x00");
|
|
9765
9854
|
if (ctx._bindingEnv && ctx._bindingEnvLoopKey === loopKey) {
|
|
9766
9855
|
return ctx._bindingEnv;
|
|
9767
9856
|
}
|
|
@@ -9776,7 +9865,7 @@ function makeBindingEnv(ctx) {
|
|
|
9776
9865
|
localFunctions: a.localFunctions,
|
|
9777
9866
|
imports: a.imports,
|
|
9778
9867
|
ambientGlobals: a.ambientGlobals,
|
|
9779
|
-
loopParams:
|
|
9868
|
+
loopParams: boundNames,
|
|
9780
9869
|
checker: a.checker
|
|
9781
9870
|
};
|
|
9782
9871
|
ctx._bindingEnv = env;
|
|
@@ -10469,7 +10558,8 @@ function transformExpressionInner(expr, ctx, node, isClientOnly) {
|
|
|
10469
10558
|
freeRefs
|
|
10470
10559
|
};
|
|
10471
10560
|
const reactive = isReactiveExpression(exprText, ctx, expr) || isReactiveOrigin(origin);
|
|
10472
|
-
const
|
|
10561
|
+
const scopeValueNames = ctx.scope.valueBoundNames();
|
|
10562
|
+
const refsLoopParam = scopeValueNames.size > 0 && Array.from(scopeValueNames).some((p) => identifierPattern(p).test(exprText));
|
|
10473
10563
|
const callsReactive = exprCallsReactiveGetters(expr, ctx);
|
|
10474
10564
|
const hasCalls = exprHasFunctionCalls(expr);
|
|
10475
10565
|
const needsSlot = reactive || isClientOnly || refsLoopParam || callsReactive || hasCalls;
|
|
@@ -10504,7 +10594,7 @@ function transformJsxFunctionCall(callExpr, jsxFunc, ctx, _isClientOnly) {
|
|
|
10504
10594
|
const substitutedGetJS = (node) => {
|
|
10505
10595
|
let text = baseGetJS(node);
|
|
10506
10596
|
for (const [paramName, argExpr] of substitutions) {
|
|
10507
|
-
text = text.replace(
|
|
10597
|
+
text = text.replace(identifierPattern(paramName, "g"), () => argExpr);
|
|
10508
10598
|
}
|
|
10509
10599
|
return text;
|
|
10510
10600
|
};
|
|
@@ -10546,7 +10636,7 @@ function transformMultiReturnJsxFunctionCall(callExpr, info, ctx) {
|
|
|
10546
10636
|
const substitutedGetJS = (node) => {
|
|
10547
10637
|
let text = baseGetJS(node);
|
|
10548
10638
|
for (const [paramName, argExpr] of substitutions) {
|
|
10549
|
-
text = text.replace(
|
|
10639
|
+
text = text.replace(identifierPattern(paramName, "g"), () => argExpr);
|
|
10550
10640
|
}
|
|
10551
10641
|
return text;
|
|
10552
10642
|
};
|
|
@@ -11557,7 +11647,7 @@ function extractItemConditionalKey(cond) {
|
|
|
11557
11647
|
return a ?? b;
|
|
11558
11648
|
}
|
|
11559
11649
|
function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
11560
|
-
const isNested = ctx.
|
|
11650
|
+
const isNested = ctx.scope.valueBoundNames().size > 0;
|
|
11561
11651
|
const diagCountAtEntry = ctx.analyzer.errors.length;
|
|
11562
11652
|
const depth = ctx.loopDepth;
|
|
11563
11653
|
const propAccess = node.expression;
|
|
@@ -11716,14 +11806,8 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
11716
11806
|
indexType = secondParam.type.getText(ctx.sourceFile);
|
|
11717
11807
|
}
|
|
11718
11808
|
}
|
|
11719
|
-
|
|
11720
|
-
|
|
11721
|
-
ctx.loopParams.add(b.name);
|
|
11722
|
-
} else {
|
|
11723
|
-
ctx.loopParams.add(param);
|
|
11724
|
-
}
|
|
11725
|
-
if (index)
|
|
11726
|
-
ctx.loopParams.add(index);
|
|
11809
|
+
const savedScope = ctx.scope;
|
|
11810
|
+
ctx.scope = ctx.scope.enterLoopRow({ param, index, paramBindings });
|
|
11727
11811
|
ctx.loopDepth++;
|
|
11728
11812
|
const tryTransformRenderableBody = (expr) => {
|
|
11729
11813
|
if (!ts12.isBinaryExpression(expr))
|
|
@@ -11784,6 +11868,24 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
11784
11868
|
}
|
|
11785
11869
|
}
|
|
11786
11870
|
const returnStmt = children.length === 0 ? body.statements.find((s) => ts12.isReturnStatement(s) && s.expression != null) : undefined;
|
|
11871
|
+
let rowScopeBeforePreamble = null;
|
|
11872
|
+
if (returnStmt) {
|
|
11873
|
+
const preambleNames = new Set;
|
|
11874
|
+
for (const stmt of body.statements) {
|
|
11875
|
+
if (stmt === returnStmt)
|
|
11876
|
+
break;
|
|
11877
|
+
collectPreambleDeclaredNames(stmt, preambleNames);
|
|
11878
|
+
}
|
|
11879
|
+
if (preambleNames.size > 0) {
|
|
11880
|
+
rowScopeBeforePreamble = ctx.scope;
|
|
11881
|
+
ctx.scope = savedScope.enterLoopRow({
|
|
11882
|
+
param,
|
|
11883
|
+
index,
|
|
11884
|
+
paramBindings,
|
|
11885
|
+
preamble: { declaredNames: [...preambleNames] }
|
|
11886
|
+
});
|
|
11887
|
+
}
|
|
11888
|
+
}
|
|
11787
11889
|
if (returnStmt && returnStmt.expression) {
|
|
11788
11890
|
let returnExpr = returnStmt.expression;
|
|
11789
11891
|
while (ts12.isParenthesizedExpression(returnExpr)) {
|
|
@@ -11853,6 +11955,9 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
11853
11955
|
}
|
|
11854
11956
|
}
|
|
11855
11957
|
}
|
|
11958
|
+
if (rowScopeBeforePreamble) {
|
|
11959
|
+
ctx.scope = rowScopeBeforePreamble;
|
|
11960
|
+
}
|
|
11856
11961
|
if (method === "flatMap" && children.length === 0 && !flatMapProjectionCall(body)) {
|
|
11857
11962
|
flatMapCallback = buildFlatMapCallback(callback, body, ctx);
|
|
11858
11963
|
}
|
|
@@ -11881,14 +11986,7 @@ function transformMapCall(node, ctx, isClientOnly = false, method = "map") {
|
|
|
11881
11986
|
}
|
|
11882
11987
|
}));
|
|
11883
11988
|
}
|
|
11884
|
-
|
|
11885
|
-
for (const b of paramBindings)
|
|
11886
|
-
ctx.loopParams.delete(b.name);
|
|
11887
|
-
} else {
|
|
11888
|
-
ctx.loopParams.delete(param);
|
|
11889
|
-
}
|
|
11890
|
-
if (index)
|
|
11891
|
-
ctx.loopParams.delete(index);
|
|
11989
|
+
ctx.scope = savedScope;
|
|
11892
11990
|
ctx.loopDepth--;
|
|
11893
11991
|
}
|
|
11894
11992
|
if (children.length === 0 && !flatMapCallback) {
|
|
@@ -12635,7 +12733,7 @@ function parseTemplateLiteral(expr, ctx) {
|
|
|
12635
12733
|
}
|
|
12636
12734
|
function tryResolveTemplateSpanFromConst(expr, ctx) {
|
|
12637
12735
|
if (ts12.isIdentifier(expr)) {
|
|
12638
|
-
if (ctx.
|
|
12736
|
+
if (ctx.scope.isBound(expr.text))
|
|
12639
12737
|
return null;
|
|
12640
12738
|
const constInfo = findLocalConst(expr.text, ctx.analyzer);
|
|
12641
12739
|
if (!constInfo)
|
|
@@ -12651,7 +12749,7 @@ function tryResolveTemplateSpanFromConst(expr, ctx) {
|
|
|
12651
12749
|
if (ts12.isElementAccessExpression(expr)) {
|
|
12652
12750
|
if (!ts12.isIdentifier(expr.expression))
|
|
12653
12751
|
return null;
|
|
12654
|
-
if (ctx.
|
|
12752
|
+
if (ctx.scope.isBound(expr.expression.text))
|
|
12655
12753
|
return null;
|
|
12656
12754
|
const constInfo = findLocalConst(expr.expression.text, ctx.analyzer);
|
|
12657
12755
|
if (!constInfo)
|
|
@@ -12730,7 +12828,7 @@ function hasDynamicTagBinding(name, sourceFile) {
|
|
|
12730
12828
|
return found;
|
|
12731
12829
|
}
|
|
12732
12830
|
function tryResolveIdentifierAsTemplateLiteral(ident, ctx) {
|
|
12733
|
-
if (ctx.
|
|
12831
|
+
if (ctx.scope.isBound(ident.text))
|
|
12734
12832
|
return null;
|
|
12735
12833
|
const constInfo = findLocalConst(ident.text, ctx.analyzer);
|
|
12736
12834
|
if (!constInfo)
|
|
@@ -13079,10 +13177,11 @@ function isSignalOrMemoArray(array, ctx) {
|
|
|
13079
13177
|
return false;
|
|
13080
13178
|
}
|
|
13081
13179
|
function referencesLoopParam(expr, ctx) {
|
|
13082
|
-
|
|
13180
|
+
const boundNames = ctx.scope.valueBoundNames();
|
|
13181
|
+
if (boundNames.size === 0)
|
|
13083
13182
|
return false;
|
|
13084
|
-
for (const p of
|
|
13085
|
-
if (
|
|
13183
|
+
for (const p of boundNames) {
|
|
13184
|
+
if (identifierPattern(p).test(expr))
|
|
13086
13185
|
return true;
|
|
13087
13186
|
}
|
|
13088
13187
|
return false;
|
|
@@ -13161,9 +13260,10 @@ function hasReactiveAttributes(attrs, ctx) {
|
|
|
13161
13260
|
if (isSignalOrMemoReference(valueToCheck, ctx) || isPropsReference(valueToCheck, ctx)) {
|
|
13162
13261
|
return true;
|
|
13163
13262
|
}
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13263
|
+
const scopeValueNames = ctx.scope.valueBoundNames();
|
|
13264
|
+
if (scopeValueNames.size > 0) {
|
|
13265
|
+
for (const p of scopeValueNames) {
|
|
13266
|
+
if (identifierPattern(p).test(valueToCheck))
|
|
13167
13267
|
return true;
|
|
13168
13268
|
}
|
|
13169
13269
|
}
|
|
@@ -13369,18 +13469,22 @@ function buildIfStatementChain(analyzer, ctx, opts) {
|
|
|
13369
13469
|
}
|
|
13370
13470
|
|
|
13371
13471
|
// ../jsx/src/ir-to-client-js/prop-handling.ts
|
|
13372
|
-
function expandDynamicPropValue(value, ctx) {
|
|
13472
|
+
function expandDynamicPropValue(value, ctx, scope) {
|
|
13373
13473
|
const trimmedValue = value.trim();
|
|
13474
|
+
if (scope?.isBound(trimmedValue))
|
|
13475
|
+
return value;
|
|
13374
13476
|
const constant = ctx.localConstants.find((c) => c.name === trimmedValue);
|
|
13375
13477
|
if (constant && constant.value) {
|
|
13376
13478
|
return constant.value;
|
|
13377
13479
|
}
|
|
13378
13480
|
return value;
|
|
13379
13481
|
}
|
|
13380
|
-
function expandConstantForReactivity(expr, ctx, originalFreeIds) {
|
|
13482
|
+
function expandConstantForReactivity(expr, ctx, originalFreeIds, scope) {
|
|
13381
13483
|
if (ctx.propsObjectName)
|
|
13382
13484
|
return { expr, freeIds: originalFreeIds };
|
|
13383
13485
|
const trimmedValue = expr.trim();
|
|
13486
|
+
if (scope?.isBound(trimmedValue))
|
|
13487
|
+
return { expr, freeIds: originalFreeIds };
|
|
13384
13488
|
const constant = ctx.localConstants.find((c) => c.name === trimmedValue);
|
|
13385
13489
|
if (constant && constant.value) {
|
|
13386
13490
|
return { expr: constant.value, freeIds: constant.freeIdentifiers };
|
|
@@ -13416,6 +13520,16 @@ function getControlledPropName(signal, propsParams, propsObjectName = null) {
|
|
|
13416
13520
|
}
|
|
13417
13521
|
|
|
13418
13522
|
// ../jsx/src/ir-to-client-js/reactivity.ts
|
|
13523
|
+
function buildLoopRowScope(loopParam, loopParamBindings, preambleNames, loopIndex) {
|
|
13524
|
+
if (!loopParam)
|
|
13525
|
+
return;
|
|
13526
|
+
return BindingScope.EMPTY.enterLoopRow({
|
|
13527
|
+
param: loopParam,
|
|
13528
|
+
paramBindings: loopParamBindings,
|
|
13529
|
+
index: loopIndex,
|
|
13530
|
+
preamble: preambleNames && preambleNames.size > 0 ? { declaredNames: [...preambleNames] } : undefined
|
|
13531
|
+
});
|
|
13532
|
+
}
|
|
13419
13533
|
function decideWrapFromAstFlags(node) {
|
|
13420
13534
|
if (node.origin && isReactiveOrigin(node.origin)) {
|
|
13421
13535
|
return { wrap: true, reason: "proven-reactive" };
|
|
@@ -13444,12 +13558,12 @@ function decideWrapForChildProp(expandedValue, ctx, prop) {
|
|
|
13444
13558
|
}
|
|
13445
13559
|
function needsEffectWrapper(expr, ctx, freeIdentifiers2) {
|
|
13446
13560
|
for (const signal of ctx.signals) {
|
|
13447
|
-
if (
|
|
13561
|
+
if (identifierCallPattern(signal.getter).test(expr)) {
|
|
13448
13562
|
return true;
|
|
13449
13563
|
}
|
|
13450
13564
|
}
|
|
13451
13565
|
for (const memo of ctx.memos) {
|
|
13452
|
-
if (
|
|
13566
|
+
if (identifierCallPattern(memo.name).test(expr)) {
|
|
13453
13567
|
return true;
|
|
13454
13568
|
}
|
|
13455
13569
|
}
|
|
@@ -13639,8 +13753,9 @@ function traverseForComponents(node, components, skipConditionals = false) {
|
|
|
13639
13753
|
}
|
|
13640
13754
|
});
|
|
13641
13755
|
}
|
|
13642
|
-
function collectLoopChildReactiveTexts(node, ctx, loopParam, loopParamBindings, stopAtReactiveConditionals = false) {
|
|
13756
|
+
function collectLoopChildReactiveTexts(node, ctx, loopParam, loopParamBindings, stopAtReactiveConditionals = false, preambleNames, loopIndex) {
|
|
13643
13757
|
const texts = [];
|
|
13758
|
+
const scope = buildLoopRowScope(loopParam, loopParamBindings, preambleNames, loopIndex);
|
|
13644
13759
|
walkIR(node, false, {
|
|
13645
13760
|
...stopAt("loop", "async", "ifStatement"),
|
|
13646
13761
|
expression: ({ node: n, scope: insideConditional }) => {
|
|
@@ -13649,7 +13764,7 @@ function collectLoopChildReactiveTexts(node, ctx, loopParam, loopParamBindings,
|
|
|
13649
13764
|
if (n.preambleRegion)
|
|
13650
13765
|
return;
|
|
13651
13766
|
const originFreeIds = freeIdsFromRefs(n.origin?.freeRefs);
|
|
13652
|
-
const expanded = expandConstantForReactivity(n.expr, ctx, originFreeIds);
|
|
13767
|
+
const expanded = expandConstantForReactivity(n.expr, ctx, originFreeIds, scope);
|
|
13653
13768
|
const reactive = classifyReactivity(expanded.expr, ctx, loopParam, loopParamBindings, expanded.freeIds).kind !== "none" || decideWrapFromAstFlags(n).wrap;
|
|
13654
13769
|
if (!reactive)
|
|
13655
13770
|
return;
|
|
@@ -13673,8 +13788,9 @@ function anyNameIn(names, set) {
|
|
|
13673
13788
|
return true;
|
|
13674
13789
|
return false;
|
|
13675
13790
|
}
|
|
13676
|
-
function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings, stopAtReactiveConditionals = false, preambleNames) {
|
|
13791
|
+
function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings, stopAtReactiveConditionals = false, preambleNames, loopIndex) {
|
|
13677
13792
|
const attrs = [];
|
|
13793
|
+
const scope = buildLoopRowScope(loopParam, loopParamBindings, preambleNames, loopIndex);
|
|
13678
13794
|
traverseElements(node, (el) => {
|
|
13679
13795
|
if (el.slotId) {
|
|
13680
13796
|
for (const attr of el.attrs) {
|
|
@@ -13687,7 +13803,7 @@ function collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings,
|
|
|
13687
13803
|
const valueStr = attrValueToString(attr.value);
|
|
13688
13804
|
if (!valueStr)
|
|
13689
13805
|
continue;
|
|
13690
|
-
const expanded = expandConstantForReactivity(valueStr, ctx, attr.freeIdentifiers);
|
|
13806
|
+
const expanded = expandConstantForReactivity(valueStr, ctx, attr.freeIdentifiers, scope);
|
|
13691
13807
|
const readsPreamble = preambleNames !== undefined && preambleNames.size > 0 && anyNameIn(expanded.freeIds ?? extractFreeIdentifiersFromText(expanded.expr), preambleNames);
|
|
13692
13808
|
const reactive = classifyReactivity(expanded.expr, ctx, loopParam, loopParamBindings, expanded.freeIds).kind !== "none" || readsPreamble || attr.callsReactiveGetters || attr.hasFunctionCalls;
|
|
13693
13809
|
if (!attr.clientOnly && !reactive)
|
|
@@ -13992,13 +14108,13 @@ function collectInnerLoops(nodes, siblingOffsets, outerLoopParam, ctx, options)
|
|
|
13992
14108
|
const emitDepth = fixedDepth ?? scope.depth + 1;
|
|
13993
14109
|
const loopParamsForTemplate = outerLoopParam ? [outerLoopParam, { param: n.param, bindings: n.paramBindings }] : undefined;
|
|
13994
14110
|
const template = n.children.map((c) => irToPlaceholderTemplate(c, undefined, emitDepth, loopParamsForTemplate)).join("");
|
|
13995
|
-
const refsOuter = outerLoopParam ?
|
|
14111
|
+
const refsOuter = outerLoopParam ? identifierPattern(outerLoopParam).test(n.array) : false;
|
|
13996
14112
|
const bindings = emptyLoopChildBindings();
|
|
13997
14113
|
const innerPreambleNames = preambleNamesOf(n);
|
|
13998
14114
|
if (ctx) {
|
|
13999
14115
|
for (const child of n.children) {
|
|
14000
|
-
bindings.reactiveTexts.push(...collectLoopChildReactiveTexts(child, ctx, n.param, n.paramBindings));
|
|
14001
|
-
bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, n.param, n.paramBindings, false, innerPreambleNames));
|
|
14116
|
+
bindings.reactiveTexts.push(...collectLoopChildReactiveTexts(child, ctx, n.param, n.paramBindings, false, innerPreambleNames, n.index));
|
|
14117
|
+
bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, n.param, n.paramBindings, false, innerPreambleNames, n.index));
|
|
14002
14118
|
bindings.refs.push(...collectLoopChildRefs(child));
|
|
14003
14119
|
}
|
|
14004
14120
|
}
|
|
@@ -14025,7 +14141,7 @@ function collectInnerLoops(nodes, siblingOffsets, outerLoopParam, ctx, options)
|
|
|
14025
14141
|
bindings.events.push(...collectLoopChildEventsWithNesting(child));
|
|
14026
14142
|
}
|
|
14027
14143
|
if (ctx) {
|
|
14028
|
-
bindings.conditionals.push(...collectLoopChildConditionals({ type: "fragment", children: n.children, loc: n.loc }, ctx, siblingOffsets, n.param, n.paramBindings));
|
|
14144
|
+
bindings.conditionals.push(...collectLoopChildConditionals({ type: "fragment", children: n.children, loc: n.loc }, ctx, siblingOffsets, n.param, n.paramBindings, innerPreambleNames, n.index));
|
|
14029
14145
|
}
|
|
14030
14146
|
}
|
|
14031
14147
|
result.push({
|
|
@@ -14221,7 +14337,7 @@ function collectElements(node, ctx, siblingOffsets, insideConditional = false) {
|
|
|
14221
14337
|
return;
|
|
14222
14338
|
const projectionInner = l.method === "flatMap" && l.children.length === 1 && l.children[0].type === "loop" ? l.children[0] : undefined;
|
|
14223
14339
|
const childHandlers = [];
|
|
14224
|
-
const bindings = projectionInner ? emptyLoopChildBindings() : collectLoopChildBindings(l.children, ctx, siblingOffsets, l.param, l.paramBindings, preambleNamesOf(l));
|
|
14340
|
+
const bindings = projectionInner ? emptyLoopChildBindings() : collectLoopChildBindings(l.children, ctx, siblingOffsets, l.param, l.paramBindings, preambleNamesOf(l), l.index);
|
|
14225
14341
|
if (!projectionInner) {
|
|
14226
14342
|
for (const child of l.children) {
|
|
14227
14343
|
childHandlers.push(...collectEventHandlersFromIR(child));
|
|
@@ -14476,7 +14592,7 @@ function collectBranchLoops(node, ctx, siblingOffsets) {
|
|
|
14476
14592
|
} else {
|
|
14477
14593
|
childTemplate = n.children.map((c) => irToHtmlTemplate(c, undefined, 0, branchLoopParamSpec)).join("");
|
|
14478
14594
|
}
|
|
14479
|
-
const branchBindings = ctx && !projectionInner ? collectLoopChildBindings(n.children, ctx, siblingOffsets, n.param, n.paramBindings, preambleNamesOf(n)) : emptyLoopChildBindings();
|
|
14595
|
+
const branchBindings = ctx && !projectionInner ? collectLoopChildBindings(n.children, ctx, siblingOffsets, n.param, n.paramBindings, preambleNamesOf(n), n.index) : emptyLoopChildBindings();
|
|
14480
14596
|
loops.push({
|
|
14481
14597
|
kind: "branch",
|
|
14482
14598
|
array: n.array,
|
|
@@ -14562,19 +14678,20 @@ function preambleNamesOf(loop) {
|
|
|
14562
14678
|
const declared = loop.preamble?.declaredNames;
|
|
14563
14679
|
return declared && declared.length > 0 ? new Set(declared) : undefined;
|
|
14564
14680
|
}
|
|
14565
|
-
function collectLoopChildBindings(children, ctx, siblingOffsets, loopParam, loopParamBindings, preambleNames) {
|
|
14681
|
+
function collectLoopChildBindings(children, ctx, siblingOffsets, loopParam, loopParamBindings, preambleNames, loopIndex) {
|
|
14566
14682
|
const bindings = emptyLoopChildBindings();
|
|
14567
14683
|
for (const child of children) {
|
|
14568
14684
|
bindings.events.push(...collectLoopChildEventsWithNesting(child));
|
|
14569
|
-
bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, loopParam, loopParamBindings, true, preambleNames));
|
|
14570
|
-
bindings.reactiveTexts.push(...collectLoopChildReactiveTexts(child, ctx, loopParam, loopParamBindings, true));
|
|
14685
|
+
bindings.reactiveAttrs.push(...collectLoopChildReactiveAttrs(child, ctx, loopParam, loopParamBindings, true, preambleNames, loopIndex));
|
|
14686
|
+
bindings.reactiveTexts.push(...collectLoopChildReactiveTexts(child, ctx, loopParam, loopParamBindings, true, preambleNames, loopIndex));
|
|
14571
14687
|
bindings.refs.push(...collectLoopChildRefs(child));
|
|
14572
|
-
bindings.conditionals.push(...collectLoopChildConditionals(child, ctx, siblingOffsets, loopParam, loopParamBindings));
|
|
14688
|
+
bindings.conditionals.push(...collectLoopChildConditionals(child, ctx, siblingOffsets, loopParam, loopParamBindings, preambleNames, loopIndex));
|
|
14573
14689
|
}
|
|
14574
14690
|
return bindings;
|
|
14575
14691
|
}
|
|
14576
|
-
function collectLoopChildConditionals(node, ctx, siblingOffsets, loopParam, loopParamBindings) {
|
|
14692
|
+
function collectLoopChildConditionals(node, ctx, siblingOffsets, loopParam, loopParamBindings, preambleNames, loopIndex) {
|
|
14577
14693
|
const conditionals = [];
|
|
14694
|
+
const scope = buildLoopRowScope(loopParam, loopParamBindings, preambleNames, loopIndex);
|
|
14578
14695
|
const refsAnyBindingViaFreeIds = (freeIds) => {
|
|
14579
14696
|
if (loopParamBindings && loopParamBindings.length > 0) {
|
|
14580
14697
|
for (const b of loopParamBindings) {
|
|
@@ -14594,7 +14711,7 @@ function collectLoopChildConditionals(node, ctx, siblingOffsets, loopParam, loop
|
|
|
14594
14711
|
const refsLoopParamInSource = refsAnyBindingViaFreeIds(sourceFreeIds);
|
|
14595
14712
|
if (!n.reactive && !refsLoopParamInSource)
|
|
14596
14713
|
return;
|
|
14597
|
-
const expanded = expandConstantForReactivity(n.condition, ctx, sourceFreeIds);
|
|
14714
|
+
const expanded = expandConstantForReactivity(n.condition, ctx, sourceFreeIds, scope);
|
|
14598
14715
|
if (classifyReactivity(expanded.expr, ctx, loopParam, loopParamBindings, expanded.freeIds).kind === "none")
|
|
14599
14716
|
return;
|
|
14600
14717
|
const loopParamsForCond = loopParam ? [{ param: loopParam, bindings: loopParamBindings }] : undefined;
|
|
@@ -14605,23 +14722,23 @@ function collectLoopChildConditionals(node, ctx, siblingOffsets, loopParam, loop
|
|
|
14605
14722
|
condition: expanded.expr,
|
|
14606
14723
|
whenTrueHtml,
|
|
14607
14724
|
whenFalseHtml,
|
|
14608
|
-
whenTrue: summarizeLoopChildBranch(n.whenTrue, ctx, siblingOffsets, loopParam, loopParamBindings),
|
|
14609
|
-
whenFalse: summarizeLoopChildBranch(n.whenFalse, ctx, siblingOffsets, loopParam, loopParamBindings),
|
|
14725
|
+
whenTrue: summarizeLoopChildBranch(n.whenTrue, ctx, siblingOffsets, loopParam, loopParamBindings, preambleNames, loopIndex),
|
|
14726
|
+
whenFalse: summarizeLoopChildBranch(n.whenFalse, ctx, siblingOffsets, loopParam, loopParamBindings, preambleNames, loopIndex),
|
|
14610
14727
|
...expanded.freeIds !== undefined && { conditionFreeIdentifiers: expanded.freeIds }
|
|
14611
14728
|
});
|
|
14612
14729
|
}
|
|
14613
14730
|
});
|
|
14614
14731
|
return conditionals;
|
|
14615
14732
|
}
|
|
14616
|
-
function summarizeLoopChildBranch(node, ctx, siblingOffsets, loopParam, loopParamBindings) {
|
|
14733
|
+
function summarizeLoopChildBranch(node, ctx, siblingOffsets, loopParam, loopParamBindings, preambleNames, loopIndex) {
|
|
14617
14734
|
const inner = collectInnerLoops([node], siblingOffsets, loopParam, ctx, branchInnerLoopOptions);
|
|
14618
14735
|
return {
|
|
14619
14736
|
childComponents: collectConditionalBranchChildComponents(node),
|
|
14620
14737
|
innerLoops: inner.length > 0 ? inner : undefined,
|
|
14621
|
-
conditionals: collectLoopChildConditionals(node, ctx, siblingOffsets, loopParam, loopParamBindings),
|
|
14738
|
+
conditionals: collectLoopChildConditionals(node, ctx, siblingOffsets, loopParam, loopParamBindings, preambleNames, loopIndex),
|
|
14622
14739
|
events: collectConditionalBranchEvents(node),
|
|
14623
|
-
reactiveAttrs: collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings, true),
|
|
14624
|
-
reactiveTexts: node.type === "expression" && node.hasFunctionCalls ? [] : collectLoopChildReactiveTexts(node, ctx, loopParam, loopParamBindings, true)
|
|
14740
|
+
reactiveAttrs: collectLoopChildReactiveAttrs(node, ctx, loopParam, loopParamBindings, true, preambleNames, loopIndex),
|
|
14741
|
+
reactiveTexts: node.type === "expression" && node.hasFunctionCalls ? [] : collectLoopChildReactiveTexts(node, ctx, loopParam, loopParamBindings, true, preambleNames, loopIndex)
|
|
14625
14742
|
};
|
|
14626
14743
|
}
|
|
14627
14744
|
|
|
@@ -15193,7 +15310,7 @@ var MODULE_CONSTANTS_PLACEHOLDER = "/* __MODULE_LEVEL_CONSTANTS__ */";
|
|
|
15193
15310
|
function detectUsedImports(code) {
|
|
15194
15311
|
const used = new Set;
|
|
15195
15312
|
for (const name of RUNTIME_IMPORT_CANDIDATES) {
|
|
15196
|
-
if (
|
|
15313
|
+
if (identifierCallPattern(name).test(code)) {
|
|
15197
15314
|
used.add(name);
|
|
15198
15315
|
}
|
|
15199
15316
|
}
|
|
@@ -15594,7 +15711,7 @@ function containsAnyIdentifier(node, names) {
|
|
|
15594
15711
|
function scanRefsByName(text, bindings) {
|
|
15595
15712
|
const result = new Map;
|
|
15596
15713
|
for (const name of bindings.keys()) {
|
|
15597
|
-
const re =
|
|
15714
|
+
const re = identifierPattern(name);
|
|
15598
15715
|
if (re.test(text))
|
|
15599
15716
|
result.set(name, []);
|
|
15600
15717
|
}
|
|
@@ -18262,7 +18379,7 @@ function buildStaticArrayDelegationPlan(elem, profileComponentName) {
|
|
|
18262
18379
|
function buildKeyedOrIndexLookup(args) {
|
|
18263
18380
|
const hasBindings = (args.paramBindings?.length ?? 0) > 0;
|
|
18264
18381
|
if (args.key !== null) {
|
|
18265
|
-
const keyWithItem = hasBindings ? substituteLoopBindings(args.key, args.paramBindings, "item") : args.key.replace(
|
|
18382
|
+
const keyWithItem = hasBindings ? substituteLoopBindings(args.key, args.paramBindings, "item") : args.key.replace(identifierPattern(args.param, "g"), "item");
|
|
18266
18383
|
return {
|
|
18267
18384
|
kind: "keyed",
|
|
18268
18385
|
arrayExpr: args.array,
|
|
@@ -20468,7 +20585,7 @@ function emitKeyedLookup(ls, ev, handlerCall, lookup) {
|
|
|
20468
20585
|
}
|
|
20469
20586
|
for (const nested of ev.nestedLoops) {
|
|
20470
20587
|
const rawKey = nested.key ?? "";
|
|
20471
|
-
const innerKeyExpr = nested.paramBindings && nested.paramBindings.length > 0 ? substituteLoopBindings(rawKey, nested.paramBindings, "item") : rawKey.replace(
|
|
20588
|
+
const innerKeyExpr = nested.paramBindings && nested.paramBindings.length > 0 ? substituteLoopBindings(rawKey, nested.paramBindings, "item") : rawKey.replace(identifierPattern(nested.param, "g"), "item");
|
|
20472
20589
|
const outerRef = hasBindings ? "__bfLoopItem" : param;
|
|
20473
20590
|
ls.push(` const ${nested.param} = ${outerRef} && ${nested.array}.find(item => String(${innerKeyExpr}) === innerKey${nested.depth})`);
|
|
20474
20591
|
}
|
|
@@ -21162,7 +21279,7 @@ function rewritePropsObjectRef(code, propsObjectName) {
|
|
|
21162
21279
|
const srcPropsName = propsObjectName ?? "props";
|
|
21163
21280
|
if (srcPropsName === PROPS_PARAM)
|
|
21164
21281
|
return code;
|
|
21165
|
-
if (!
|
|
21282
|
+
if (!identifierPattern(srcPropsName).test(code))
|
|
21166
21283
|
return code;
|
|
21167
21284
|
const sourceFile = ts19.createSourceFile("init-body.ts", code, ts19.ScriptTarget.Latest, true, ts19.ScriptKind.TS);
|
|
21168
21285
|
const spans = [];
|
|
@@ -23572,7 +23689,7 @@ class JsxAdapter extends BaseAdapter {
|
|
|
23572
23689
|
lines.push(` const ${signal.getter} = () => ${initialValue}`);
|
|
23573
23690
|
}
|
|
23574
23691
|
if (signal.setter) {
|
|
23575
|
-
const setterUsed =
|
|
23692
|
+
const setterUsed = identifierPattern(signal.setter).test(setterRefText);
|
|
23576
23693
|
if (setterUsed) {
|
|
23577
23694
|
lines.push(` const ${signal.setter} = (..._args: any[]) => {}`);
|
|
23578
23695
|
}
|
|
@@ -23592,7 +23709,7 @@ class JsxAdapter extends BaseAdapter {
|
|
|
23592
23709
|
continue;
|
|
23593
23710
|
const keyword = constant.declarationKind ?? "const";
|
|
23594
23711
|
if (!constant.value) {
|
|
23595
|
-
const typeAnnotation = preserveTypes && constant.type ? `: ${constant.type
|
|
23712
|
+
const typeAnnotation = preserveTypes && (constant.typeAnnotation ?? constant.type) ? `: ${constant.typeAnnotation ?? constant.type?.raw}` : "";
|
|
23596
23713
|
lines.push(` ${keyword} ${constant.name}${typeAnnotation}`);
|
|
23597
23714
|
continue;
|
|
23598
23715
|
}
|
|
@@ -23602,7 +23719,8 @@ class JsxAdapter extends BaseAdapter {
|
|
|
23602
23719
|
if (!reachable.has(constant.name))
|
|
23603
23720
|
continue;
|
|
23604
23721
|
const constValue = preserveTypes ? constant.typedValue ?? constant.value : constant.value;
|
|
23605
|
-
|
|
23722
|
+
const letTypeAnnotation = preserveTypes && keyword === "let" && constant.typeAnnotation ? `: ${constant.typeAnnotation}` : "";
|
|
23723
|
+
lines.push(` ${keyword} ${constant.name}${letTypeAnnotation} = ${constValue}`);
|
|
23606
23724
|
}
|
|
23607
23725
|
for (const func of localFunctions) {
|
|
23608
23726
|
if (moduleScopeNames.has(func.name))
|
|
@@ -23709,7 +23827,8 @@ class JsxAdapter extends BaseAdapter {
|
|
|
23709
23827
|
const keyword = c.declarationKind ?? "const";
|
|
23710
23828
|
const exportKw = c.isExported ? "export " : "";
|
|
23711
23829
|
if (!c.value) {
|
|
23712
|
-
|
|
23830
|
+
const typeAnnotation = preserveTypes && (c.typeAnnotation ?? c.type) ? `: ${c.typeAnnotation ?? c.type?.raw}` : "";
|
|
23831
|
+
entries.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}${typeAnnotation}` });
|
|
23713
23832
|
continue;
|
|
23714
23833
|
}
|
|
23715
23834
|
const trimmed = c.value.trim();
|
|
@@ -23718,7 +23837,8 @@ class JsxAdapter extends BaseAdapter {
|
|
|
23718
23837
|
if (c.isExported && /^createContext\b/.test(trimmed))
|
|
23719
23838
|
continue;
|
|
23720
23839
|
const value = preserveTypes ? c.typedValue ?? c.value : c.value;
|
|
23721
|
-
|
|
23840
|
+
const letTypeAnnotation = preserveTypes && keyword === "let" && c.typeAnnotation ? `: ${c.typeAnnotation}` : "";
|
|
23841
|
+
entries.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}${letTypeAnnotation} = ${value}` });
|
|
23722
23842
|
}
|
|
23723
23843
|
for (const f of ir.metadata.localFunctions) {
|
|
23724
23844
|
if (!f.isModule || !moduleNames.has(f.name))
|
|
@@ -23767,6 +23887,7 @@ class JsxAdapter extends BaseAdapter {
|
|
|
23767
23887
|
}
|
|
23768
23888
|
|
|
23769
23889
|
// ../jsx/src/adapters/template-imports.ts
|
|
23890
|
+
import ts25 from "typescript";
|
|
23770
23891
|
var CLIENT_PACKAGE_SOURCES = new Set([
|
|
23771
23892
|
"@barefootjs/client",
|
|
23772
23893
|
"@barefootjs/client/runtime"
|
|
@@ -24156,11 +24277,11 @@ function registerBuiltinLoweringPlugins() {
|
|
|
24156
24277
|
registerLoweringPlugin(plugin);
|
|
24157
24278
|
}
|
|
24158
24279
|
// ../jsx/src/combine-client-js.ts
|
|
24159
|
-
import ts25 from "typescript";
|
|
24160
|
-
// ../jsx/src/debug.ts
|
|
24161
24280
|
import ts26 from "typescript";
|
|
24162
|
-
// ../jsx/src/
|
|
24281
|
+
// ../jsx/src/debug.ts
|
|
24163
24282
|
import ts27 from "typescript";
|
|
24283
|
+
// ../jsx/src/profiler.ts
|
|
24284
|
+
import ts28 from "typescript";
|
|
24164
24285
|
|
|
24165
24286
|
// ../jsx/src/index.ts
|
|
24166
24287
|
registerBuiltinLoweringPlugins();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/vite",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.4",
|
|
4
4
|
"description": "Vite plugin for BarefootJS: Vite/Rollup owns bundling, hashing, chunking, tree-shaking and minification of client assets, BarefootJS keeps only the JSX to (template, client JS) compile",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,17 +38,17 @@
|
|
|
38
38
|
"directory": "packages/vite"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@barefootjs/shared": "0.31.
|
|
41
|
+
"@barefootjs/shared": "0.31.4"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@barefootjs/jsx": ">=0.2.0",
|
|
45
45
|
"vite": "^6.0.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@barefootjs/client": "0.31.
|
|
49
|
-
"@barefootjs/go-template": "0.31.
|
|
50
|
-
"@barefootjs/hono": "0.31.
|
|
51
|
-
"@barefootjs/jsx": "0.31.
|
|
48
|
+
"@barefootjs/client": "0.31.4",
|
|
49
|
+
"@barefootjs/go-template": "0.31.4",
|
|
50
|
+
"@barefootjs/hono": "0.31.4",
|
|
51
|
+
"@barefootjs/jsx": "0.31.4",
|
|
52
52
|
"typescript": "^5.0.0",
|
|
53
53
|
"vite": "^6.0.0"
|
|
54
54
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression (#2588): a relative specifier inside a DYNAMIC `import()` must
|
|
3
|
+
* be re-anchored to the emitted template's directory, exactly like the
|
|
4
|
+
* static `import` statements `rewriteImportsForTemplate` already handles.
|
|
5
|
+
*
|
|
6
|
+
* Dynamic imports never reach `ir.metadata.templateImports` — they ride
|
|
7
|
+
* along inside declaration source text that the adapter re-emits verbatim
|
|
8
|
+
* (`generateModuleScopeDeclarations`' consts/functions, and a component
|
|
9
|
+
* body's local handlers). Before the fix they were emitted untouched, so a
|
|
10
|
+
* specifier written relative to `components/` still said `../lib/heavy`
|
|
11
|
+
* once the template landed in `app/dist/components/` — a path that does
|
|
12
|
+
* not exist. The backend bundler then hard-fails (`Could not resolve
|
|
13
|
+
* "../lib/heavy"`), so this is a build break, not a type-only defect.
|
|
14
|
+
*
|
|
15
|
+
* The fixture mirrors the layout that hits this in the wild (piconic-ai/koma):
|
|
16
|
+
* a `components` dir and a plain `lib` dir side by side, with templates
|
|
17
|
+
* emitted to a DEEPER directory — root-relative and template-relative only
|
|
18
|
+
* diverge when the two depths differ, so a flat layout would not reproduce.
|
|
19
|
+
* Lives under `packages/vite/` (not a system tmpdir) so `@barefootjs/client`
|
|
20
|
+
* resolves through the monorepo's real workspace symlinks — same reason
|
|
21
|
+
* `e2e-fixture`/`e2e-fixture-dev`/`e2e-fixture-relimport` do.
|
|
22
|
+
*/
|
|
23
|
+
import { describe, test, expect, afterAll } from 'bun:test'
|
|
24
|
+
import { build } from 'vite'
|
|
25
|
+
import { mkdtemp, rm, readFile } from 'node:fs/promises'
|
|
26
|
+
import { tmpdir } from 'node:os'
|
|
27
|
+
import { join, resolve } from 'node:path'
|
|
28
|
+
import { HonoAdapter } from '@barefootjs/hono/adapter'
|
|
29
|
+
import { barefoot } from '../plugin.ts'
|
|
30
|
+
|
|
31
|
+
const FIXTURE_ROOT = resolve(import.meta.dirname, '../../e2e-fixture-dynimport')
|
|
32
|
+
const APP_ROOT = join(FIXTURE_ROOT, 'app')
|
|
33
|
+
const COMPONENTS_DIR = join(FIXTURE_ROOT, 'components')
|
|
34
|
+
|
|
35
|
+
// `app/dist/components/Lazy.tsx` → up three → the fixture root, where `lib/`
|
|
36
|
+
// sits. The source says `../lib/heavy` from `components/`; the emitted
|
|
37
|
+
// template has to say this instead.
|
|
38
|
+
const REANCHORED = '../../../lib/heavy'
|
|
39
|
+
|
|
40
|
+
describe('dynamic import() re-anchoring in emitted templates', () => {
|
|
41
|
+
let outDir: string
|
|
42
|
+
let templatesDir: string
|
|
43
|
+
|
|
44
|
+
afterAll(async () => {
|
|
45
|
+
await rm(outDir, { recursive: true, force: true })
|
|
46
|
+
await rm(join(APP_ROOT, 'dist'), { recursive: true, force: true })
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
test('re-anchors dynamic imports at module scope, in type position, and inside a component body', async () => {
|
|
50
|
+
outDir = await mkdtemp(join(tmpdir(), 'barefoot-vite-dynimport-dist-'))
|
|
51
|
+
templatesDir = join(APP_ROOT, 'dist/components')
|
|
52
|
+
|
|
53
|
+
await build({
|
|
54
|
+
configFile: false,
|
|
55
|
+
root: APP_ROOT,
|
|
56
|
+
base: '/static/',
|
|
57
|
+
logLevel: 'warn',
|
|
58
|
+
build: { outDir, emptyOutDir: true },
|
|
59
|
+
plugins: [
|
|
60
|
+
barefoot({
|
|
61
|
+
adapter: new HonoAdapter(),
|
|
62
|
+
components: [COMPONENTS_DIR],
|
|
63
|
+
templates: templatesDir,
|
|
64
|
+
}),
|
|
65
|
+
],
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const template = await readFile(join(templatesDir, 'Lazy.tsx'), 'utf8')
|
|
69
|
+
|
|
70
|
+
// Nothing anywhere may still carry the source-relative form. Asserted
|
|
71
|
+
// first and globally: a per-site check would pass while some fourth
|
|
72
|
+
// emission path silently leaked the old specifier.
|
|
73
|
+
expect(template).not.toContain("'../lib/heavy'")
|
|
74
|
+
|
|
75
|
+
// Module scope, TYPE position — `typeof import('…')` is an
|
|
76
|
+
// ImportTypeNode, a different AST node from the call expression below,
|
|
77
|
+
// and was missed independently.
|
|
78
|
+
expect(template).toContain(`typeof import('${REANCHORED}')`)
|
|
79
|
+
|
|
80
|
+
// Module scope, VALUE position — inside a re-emitted const's body.
|
|
81
|
+
expect(template).toContain(`modPromise = import('${REANCHORED}')`)
|
|
82
|
+
|
|
83
|
+
// Component scope — inside a local handler in the component body,
|
|
84
|
+
// which is emitted by a different code path than module declarations.
|
|
85
|
+
expect(template).toContain(`await import('${REANCHORED}')`)
|
|
86
|
+
|
|
87
|
+
// The re-anchored path must actually resolve on disk from the emitted
|
|
88
|
+
// template's own directory — the assertions above only pin the string.
|
|
89
|
+
const target = resolve(templatesDir, REANCHORED + '.ts')
|
|
90
|
+
expect(await readFile(target, 'utf8')).toContain('export function heavy')
|
|
91
|
+
}, 60_000)
|
|
92
|
+
})
|