@fictjs/compiler 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +329 -249
- package/dist/index.js +329 -249
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -14279,6 +14279,35 @@ var SAFE_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
|
14279
14279
|
"Date.parse"
|
|
14280
14280
|
]);
|
|
14281
14281
|
|
|
14282
|
+
// src/debug.ts
|
|
14283
|
+
function parseFlag(raw) {
|
|
14284
|
+
if (!raw) return false;
|
|
14285
|
+
const val = raw.toLowerCase();
|
|
14286
|
+
return val === "1" || val === "true" || val === "yes" || val === "on";
|
|
14287
|
+
}
|
|
14288
|
+
function debugEnabled(flag) {
|
|
14289
|
+
const normalized = flag.toLowerCase();
|
|
14290
|
+
const legacy = process.env[`DEBUG_${flag.toUpperCase()}`];
|
|
14291
|
+
if (parseFlag(legacy)) return true;
|
|
14292
|
+
const fictLegacy = process.env[`FICT_DEBUG_${flag.toUpperCase()}`];
|
|
14293
|
+
if (parseFlag(fictLegacy)) return true;
|
|
14294
|
+
const raw = process.env.FICT_DEBUG ?? process.env.DEBUG_FICT;
|
|
14295
|
+
if (!raw) return false;
|
|
14296
|
+
if (parseFlag(raw)) return true;
|
|
14297
|
+
const parts = raw.split(",").map((p) => p.trim().toLowerCase()).filter(Boolean);
|
|
14298
|
+
return parts.includes(normalized) || parts.includes("all");
|
|
14299
|
+
}
|
|
14300
|
+
function debugLog(flag, message, data) {
|
|
14301
|
+
if (!debugEnabled(flag)) return;
|
|
14302
|
+
const msg = typeof message === "function" ? message() : message;
|
|
14303
|
+
const prefix = `[fict:${flag}]`;
|
|
14304
|
+
if (data !== void 0) {
|
|
14305
|
+
console.log(prefix, msg, data);
|
|
14306
|
+
} else {
|
|
14307
|
+
console.log(prefix, msg);
|
|
14308
|
+
}
|
|
14309
|
+
}
|
|
14310
|
+
|
|
14282
14311
|
// src/ir/build-hir.ts
|
|
14283
14312
|
var t = __toESM(require_lib3(), 1);
|
|
14284
14313
|
|
|
@@ -15680,7 +15709,7 @@ function convertExpression(node) {
|
|
|
15680
15709
|
}
|
|
15681
15710
|
if (t.isObjectMethod(prop)) {
|
|
15682
15711
|
if (prop.computed) return void 0;
|
|
15683
|
-
const keyExpr2 = t.isIdentifier(prop.key) ? { kind: "Identifier", name: prop.key.name } : t.isStringLiteral(prop.key) ? { kind: "Literal", value: prop.key.value } : void 0;
|
|
15712
|
+
const keyExpr2 = t.isIdentifier(prop.key) ? { kind: "Identifier", name: prop.key.name } : t.isStringLiteral(prop.key) ? { kind: "Literal", value: prop.key.value } : t.isNumericLiteral(prop.key) ? { kind: "Literal", value: prop.key.value } : void 0;
|
|
15684
15713
|
if (!keyExpr2) return void 0;
|
|
15685
15714
|
const fnExpr = t.functionExpression(
|
|
15686
15715
|
null,
|
|
@@ -15697,7 +15726,7 @@ function convertExpression(node) {
|
|
|
15697
15726
|
};
|
|
15698
15727
|
}
|
|
15699
15728
|
if (!t.isObjectProperty(prop) || prop.computed) return void 0;
|
|
15700
|
-
const keyExpr = t.isIdentifier(prop.key) ? { kind: "Identifier", name: prop.key.name } : t.isStringLiteral(prop.key) ? { kind: "Literal", value: prop.key.value } : void 0;
|
|
15729
|
+
const keyExpr = t.isIdentifier(prop.key) ? { kind: "Identifier", name: prop.key.name } : t.isStringLiteral(prop.key) ? { kind: "Literal", value: prop.key.value } : t.isNumericLiteral(prop.key) ? { kind: "Literal", value: prop.key.value } : void 0;
|
|
15701
15730
|
if (!keyExpr) return void 0;
|
|
15702
15731
|
if (!t.isExpression(prop.value)) return void 0;
|
|
15703
15732
|
return {
|
|
@@ -16039,23 +16068,6 @@ function convertJSXMemberExpr(node) {
|
|
|
16039
16068
|
};
|
|
16040
16069
|
}
|
|
16041
16070
|
|
|
16042
|
-
// src/debug.ts
|
|
16043
|
-
function parseFlag(raw) {
|
|
16044
|
-
if (!raw) return false;
|
|
16045
|
-
const val = raw.toLowerCase();
|
|
16046
|
-
return val === "1" || val === "true" || val === "yes" || val === "on";
|
|
16047
|
-
}
|
|
16048
|
-
function debugEnabled(flag) {
|
|
16049
|
-
const normalized = flag.toLowerCase();
|
|
16050
|
-
const legacy = process.env[`DEBUG_${flag.toUpperCase()}`];
|
|
16051
|
-
if (parseFlag(legacy)) return true;
|
|
16052
|
-
const raw = process.env.FICT_DEBUG ?? process.env.DEBUG_FICT;
|
|
16053
|
-
if (!raw) return false;
|
|
16054
|
-
if (parseFlag(raw)) return true;
|
|
16055
|
-
const parts = raw.split(",").map((p) => p.trim().toLowerCase()).filter(Boolean);
|
|
16056
|
-
return parts.includes(normalized) || parts.includes("all");
|
|
16057
|
-
}
|
|
16058
|
-
|
|
16059
16071
|
// src/fine-grained-dom.ts
|
|
16060
16072
|
function normalizeDependencyKey(name) {
|
|
16061
16073
|
return name.split(".").map((part) => part.replace(/_\d+$/, "")).join(".");
|
|
@@ -18105,6 +18117,35 @@ function structurizeTry(ctx, block, term) {
|
|
|
18105
18117
|
|
|
18106
18118
|
// src/ir/regions.ts
|
|
18107
18119
|
var REACTIVE_CREATORS = /* @__PURE__ */ new Set(["createEffect", "createMemo", "createSelector"]);
|
|
18120
|
+
function buildEffectCall(ctx, t2, effectFn, options) {
|
|
18121
|
+
if (ctx.inModule) {
|
|
18122
|
+
ctx.helpersUsed.add("effect");
|
|
18123
|
+
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.effect), [effectFn]);
|
|
18124
|
+
}
|
|
18125
|
+
ctx.helpersUsed.add("useEffect");
|
|
18126
|
+
ctx.needsCtx = true;
|
|
18127
|
+
const args = [t2.identifier("__fictCtx"), effectFn];
|
|
18128
|
+
const slot = options?.slot;
|
|
18129
|
+
if (options?.forceSlot) {
|
|
18130
|
+
args.push(slot !== void 0 && slot >= 0 ? t2.numericLiteral(slot) : t2.identifier("undefined"));
|
|
18131
|
+
} else if (slot !== void 0 && slot >= 0) {
|
|
18132
|
+
args.push(t2.numericLiteral(slot));
|
|
18133
|
+
}
|
|
18134
|
+
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), args);
|
|
18135
|
+
}
|
|
18136
|
+
function buildMemoCall(ctx, t2, memoFn, slot) {
|
|
18137
|
+
if (ctx.inModule) {
|
|
18138
|
+
ctx.helpersUsed.add("memo");
|
|
18139
|
+
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.memo), [memoFn]);
|
|
18140
|
+
}
|
|
18141
|
+
ctx.helpersUsed.add("useMemo");
|
|
18142
|
+
ctx.needsCtx = true;
|
|
18143
|
+
const args = [t2.identifier("__fictCtx"), memoFn];
|
|
18144
|
+
if (slot !== void 0 && slot >= 0) {
|
|
18145
|
+
args.push(t2.numericLiteral(slot));
|
|
18146
|
+
}
|
|
18147
|
+
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.useMemo), args);
|
|
18148
|
+
}
|
|
18108
18149
|
function expressionCreatesReactive(expr) {
|
|
18109
18150
|
if (expr.kind === "CallExpression" && expr.callee.kind === "Identifier") {
|
|
18110
18151
|
const base = getSSABaseName(expr.callee.name);
|
|
@@ -18395,8 +18436,10 @@ function expressionUsesTracked(expr, ctx) {
|
|
|
18395
18436
|
case "Identifier":
|
|
18396
18437
|
return ctx.trackedVars.has(deSSAVarName(expr.name)) || (ctx.externalTracked?.has(deSSAVarName(expr.name)) ?? false) || (ctx.memoVars?.has(deSSAVarName(expr.name)) ?? false) || (ctx.aliasVars?.has(deSSAVarName(expr.name)) ?? false);
|
|
18397
18438
|
case "MemberExpression":
|
|
18439
|
+
case "OptionalMemberExpression":
|
|
18398
18440
|
return expressionUsesTracked(expr.object, ctx);
|
|
18399
18441
|
case "CallExpression":
|
|
18442
|
+
case "OptionalCallExpression":
|
|
18400
18443
|
if (expressionUsesTracked(expr.callee, ctx)) return true;
|
|
18401
18444
|
return expr.arguments.some((arg) => expressionUsesTracked(arg, ctx));
|
|
18402
18445
|
case "LogicalExpression":
|
|
@@ -18618,16 +18661,8 @@ function lowerNodeWithRegionContext(node, t2, ctx, declaredVars, regionCtx) {
|
|
|
18618
18661
|
const inNonReactiveScope = !!(ctx.nonReactiveScopeDepth && ctx.nonReactiveScopeDepth > 0);
|
|
18619
18662
|
const shouldWrapEffect = ctx.wrapTrackedExpressions !== false && !ctx.inRegionMemo && !inNonReactiveScope && expressionUsesTracked(node.test, ctx) && !statementHasEarlyExit(ifStmt, t2);
|
|
18620
18663
|
if (shouldWrapEffect) {
|
|
18621
|
-
|
|
18622
|
-
ctx
|
|
18623
|
-
return [
|
|
18624
|
-
t2.expressionStatement(
|
|
18625
|
-
t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), [
|
|
18626
|
-
t2.identifier("__fictCtx"),
|
|
18627
|
-
t2.arrowFunctionExpression([], t2.blockStatement([ifStmt]))
|
|
18628
|
-
])
|
|
18629
|
-
)
|
|
18630
|
-
];
|
|
18664
|
+
const effectFn = t2.arrowFunctionExpression([], t2.blockStatement([ifStmt]));
|
|
18665
|
+
return [t2.expressionStatement(buildEffectCall(ctx, t2, effectFn))];
|
|
18631
18666
|
}
|
|
18632
18667
|
return [ifStmt];
|
|
18633
18668
|
}
|
|
@@ -18892,16 +18927,8 @@ function lowerStructuredNodeForRegion(node, region, t2, ctx, declaredVars, regio
|
|
|
18892
18927
|
ifStmt = buildIfStmt(consequent, alternate);
|
|
18893
18928
|
}
|
|
18894
18929
|
if (shouldWrapEffect) {
|
|
18895
|
-
|
|
18896
|
-
ctx
|
|
18897
|
-
return [
|
|
18898
|
-
t2.expressionStatement(
|
|
18899
|
-
t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), [
|
|
18900
|
-
t2.identifier("__fictCtx"),
|
|
18901
|
-
t2.arrowFunctionExpression([], t2.blockStatement([ifStmt]))
|
|
18902
|
-
])
|
|
18903
|
-
)
|
|
18904
|
-
];
|
|
18930
|
+
const effectFn = t2.arrowFunctionExpression([], t2.blockStatement([ifStmt]));
|
|
18931
|
+
return [t2.expressionStatement(buildEffectCall(ctx, t2, effectFn))];
|
|
18905
18932
|
}
|
|
18906
18933
|
return [ifStmt];
|
|
18907
18934
|
}
|
|
@@ -19273,30 +19300,16 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
19273
19300
|
const outputNames = outputNamesOverride ?? Array.from(region.declarations).map((name) => deSSAVarName(name));
|
|
19274
19301
|
const uniqueOutputNames = [...new Set(outputNames)];
|
|
19275
19302
|
const bindableOutputs = uniqueOutputNames.filter((name) => !declaredVars.has(name));
|
|
19276
|
-
|
|
19277
|
-
|
|
19278
|
-
|
|
19279
|
-
|
|
19280
|
-
});
|
|
19281
|
-
}
|
|
19303
|
+
debugLog("region", `Region memo ${region.id}`, {
|
|
19304
|
+
instructions: region.instructions.map((instr) => instr.kind),
|
|
19305
|
+
outputs: uniqueOutputNames
|
|
19306
|
+
});
|
|
19282
19307
|
if (uniqueOutputNames.length === 0) {
|
|
19283
|
-
|
|
19284
|
-
ctx.
|
|
19285
|
-
const
|
|
19286
|
-
t2.identifier("__fictCtx"),
|
|
19287
|
-
t2.arrowFunctionExpression([], t2.blockStatement(bodyStatements))
|
|
19288
|
-
];
|
|
19289
|
-
{
|
|
19290
|
-
const slot = reserveHookSlot(ctx);
|
|
19291
|
-
if (slot >= 0) {
|
|
19292
|
-
effectCallArgs.push(t2.numericLiteral(slot));
|
|
19293
|
-
}
|
|
19294
|
-
}
|
|
19295
|
-
const effectCall = t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), effectCallArgs);
|
|
19308
|
+
const effectFn = t2.arrowFunctionExpression([], t2.blockStatement(bodyStatements));
|
|
19309
|
+
const slot = ctx.inModule ? void 0 : reserveHookSlot(ctx);
|
|
19310
|
+
const effectCall = buildEffectCall(ctx, t2, effectFn, { slot });
|
|
19296
19311
|
statements.push(t2.expressionStatement(effectCall));
|
|
19297
19312
|
} else {
|
|
19298
|
-
ctx.helpersUsed.add("useMemo");
|
|
19299
|
-
ctx.needsCtx = true;
|
|
19300
19313
|
if (!bodyStatementsOverride) {
|
|
19301
19314
|
const lazyInfo = analyzeHIRConditionalUsage(region, ctx);
|
|
19302
19315
|
if (lazyInfo) {
|
|
@@ -19325,15 +19338,8 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
19325
19338
|
};
|
|
19326
19339
|
const returnObj = t2.objectExpression(uniqueOutputNames.map((name) => buildOutputProperty(name)));
|
|
19327
19340
|
const memoBody = t2.blockStatement([...bodyStatements, t2.returnStatement(returnObj)]);
|
|
19328
|
-
const slot = reserveHookSlot(ctx);
|
|
19329
|
-
const
|
|
19330
|
-
t2.identifier("__fictCtx"),
|
|
19331
|
-
t2.arrowFunctionExpression([], memoBody)
|
|
19332
|
-
];
|
|
19333
|
-
if (slot >= 0) {
|
|
19334
|
-
memoArgs.push(t2.numericLiteral(slot));
|
|
19335
|
-
}
|
|
19336
|
-
const memoCall = t2.callExpression(t2.identifier(RUNTIME_ALIASES.useMemo), memoArgs);
|
|
19341
|
+
const slot = ctx.inModule ? void 0 : reserveHookSlot(ctx);
|
|
19342
|
+
const memoCall = buildMemoCall(ctx, t2, t2.arrowFunctionExpression([], memoBody), slot);
|
|
19337
19343
|
const regionVarName = `__region_${region.id}`;
|
|
19338
19344
|
statements.push(
|
|
19339
19345
|
t2.variableDeclaration("const", [t2.variableDeclarator(t2.identifier(regionVarName), memoCall)])
|
|
@@ -19343,16 +19349,13 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
19343
19349
|
(name) => ctx.trackedVars.has(name) && !isAccessorOutput(name)
|
|
19344
19350
|
);
|
|
19345
19351
|
const directOutputs = bindableOutputs.filter((name) => !getterOutputs.includes(name));
|
|
19346
|
-
|
|
19347
|
-
|
|
19348
|
-
|
|
19349
|
-
|
|
19350
|
-
|
|
19351
|
-
|
|
19352
|
-
|
|
19353
|
-
memoVars: Array.from(ctx.memoVars ?? [])
|
|
19354
|
-
});
|
|
19355
|
-
}
|
|
19352
|
+
debugLog("region", `Region debug ${region.id}`, {
|
|
19353
|
+
outputs: uniqueOutputNames,
|
|
19354
|
+
getterOutputs,
|
|
19355
|
+
directOutputs,
|
|
19356
|
+
tracked: Array.from(ctx.trackedVars),
|
|
19357
|
+
memoVars: Array.from(ctx.memoVars ?? [])
|
|
19358
|
+
});
|
|
19356
19359
|
if (directOutputs.length > 0) {
|
|
19357
19360
|
directOutputs.forEach((name) => declaredVars.add(name));
|
|
19358
19361
|
statements.push(
|
|
@@ -19380,21 +19383,15 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
19380
19383
|
ctx.memoVars?.add(name);
|
|
19381
19384
|
}
|
|
19382
19385
|
if (region.hasControlFlow && getterOutputs.length > 0) {
|
|
19383
|
-
ctx.helpersUsed.add("useEffect");
|
|
19384
|
-
ctx.needsCtx = true;
|
|
19385
19386
|
const effectBody = t2.blockStatement(
|
|
19386
19387
|
getterOutputs.map((name) => t2.expressionStatement(t2.callExpression(t2.identifier(name), [])))
|
|
19387
19388
|
);
|
|
19388
19389
|
statements.push(
|
|
19389
19390
|
t2.expressionStatement(
|
|
19390
|
-
|
|
19391
|
-
|
|
19392
|
-
|
|
19393
|
-
|
|
19394
|
-
const slot2 = reserveHookSlot(ctx);
|
|
19395
|
-
return slot2 >= 0 ? t2.numericLiteral(slot2) : t2.identifier("undefined");
|
|
19396
|
-
})()
|
|
19397
|
-
])
|
|
19391
|
+
buildEffectCall(ctx, t2, t2.arrowFunctionExpression([], effectBody), {
|
|
19392
|
+
slot: ctx.inModule ? void 0 : reserveHookSlot(ctx),
|
|
19393
|
+
forceSlot: true
|
|
19394
|
+
})
|
|
19398
19395
|
)
|
|
19399
19396
|
);
|
|
19400
19397
|
}
|
|
@@ -19608,18 +19605,13 @@ function generateLazyConditionalMemo(region, orderedOutputs, bodyStatements, con
|
|
|
19608
19605
|
t2.ifStatement(conditionId, t2.blockStatement(trueBlock), t2.blockStatement(falseBlock))
|
|
19609
19606
|
);
|
|
19610
19607
|
}
|
|
19611
|
-
ctx.helpersUsed.add("useMemo");
|
|
19612
|
-
ctx.needsCtx = true;
|
|
19613
19608
|
const regionVarName = `__region_${region.id}`;
|
|
19614
|
-
const
|
|
19615
|
-
|
|
19616
|
-
t2
|
|
19617
|
-
t2.arrowFunctionExpression([], t2.blockStatement(memoBody))
|
|
19618
|
-
|
|
19619
|
-
|
|
19620
|
-
memoArgs.push(t2.numericLiteral(slotForMemo));
|
|
19621
|
-
}
|
|
19622
|
-
const memoCall = t2.callExpression(t2.identifier("__fictUseMemo"), memoArgs);
|
|
19609
|
+
const memoCall = buildMemoCall(
|
|
19610
|
+
ctx,
|
|
19611
|
+
t2,
|
|
19612
|
+
t2.arrowFunctionExpression([], t2.blockStatement(memoBody)),
|
|
19613
|
+
ctx.inModule ? void 0 : reserveHookSlot(ctx)
|
|
19614
|
+
);
|
|
19623
19615
|
statements.push(
|
|
19624
19616
|
t2.variableDeclaration("const", [t2.variableDeclarator(t2.identifier(regionVarName), memoCall)])
|
|
19625
19617
|
);
|
|
@@ -19708,20 +19700,9 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19708
19700
|
const isReactiveObjectCall = instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && ["mergeProps"].includes(instr.value.callee.name);
|
|
19709
19701
|
const isMemoReturningCall = isAccessorReturningCall || isReactiveObjectCall;
|
|
19710
19702
|
const lowerAssignedValue = (forceAssigned = false) => lowerExpressionWithDeSSA(instr.value, ctx, forceAssigned || isFunctionValue);
|
|
19711
|
-
const
|
|
19712
|
-
const
|
|
19713
|
-
|
|
19714
|
-
t2.arrowFunctionExpression([], expr)
|
|
19715
|
-
];
|
|
19716
|
-
if (inRegionMemo) {
|
|
19717
|
-
const slot = reserveHookSlot(ctx);
|
|
19718
|
-
if (slot >= 0) {
|
|
19719
|
-
args.push(t2.numericLiteral(slot));
|
|
19720
|
-
}
|
|
19721
|
-
}
|
|
19722
|
-
ctx.helpersUsed.add("useMemo");
|
|
19723
|
-
ctx.needsCtx = true;
|
|
19724
|
-
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.useMemo), args);
|
|
19703
|
+
const buildDerivedMemoCall = (expr) => {
|
|
19704
|
+
const slot = !ctx.inModule && inRegionMemo ? reserveHookSlot(ctx) : void 0;
|
|
19705
|
+
return buildMemoCall(ctx, t2, t2.arrowFunctionExpression([], expr), slot);
|
|
19725
19706
|
};
|
|
19726
19707
|
if (isShadowDeclaration && declKind) {
|
|
19727
19708
|
ctx.trackedVars.delete(baseName2);
|
|
@@ -19760,7 +19741,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19760
19741
|
return t2.variableDeclaration(normalizedDecl, [
|
|
19761
19742
|
t2.variableDeclarator(
|
|
19762
19743
|
t2.identifier(baseName2),
|
|
19763
|
-
isMemoReturningCall ? derivedExpr :
|
|
19744
|
+
isMemoReturningCall ? derivedExpr : buildDerivedMemoCall(derivedExpr)
|
|
19764
19745
|
)
|
|
19765
19746
|
]);
|
|
19766
19747
|
}
|
|
@@ -19787,7 +19768,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19787
19768
|
return t2.variableDeclaration(normalizedDecl, [
|
|
19788
19769
|
t2.variableDeclarator(
|
|
19789
19770
|
t2.identifier(baseName2),
|
|
19790
|
-
isMemoReturningCall ? derivedExpr :
|
|
19771
|
+
isMemoReturningCall ? derivedExpr : buildDerivedMemoCall(derivedExpr)
|
|
19791
19772
|
)
|
|
19792
19773
|
]);
|
|
19793
19774
|
}
|
|
@@ -19796,7 +19777,14 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19796
19777
|
]);
|
|
19797
19778
|
}
|
|
19798
19779
|
if (aliasVars.has(baseName2) && declaredVars.has(baseName2)) {
|
|
19799
|
-
throw new Error(
|
|
19780
|
+
throw new Error(
|
|
19781
|
+
`Alias reassignment is not supported for "${baseName2}".
|
|
19782
|
+
|
|
19783
|
+
"${baseName2}" was assigned from a reactive value and cannot be reassigned.
|
|
19784
|
+
Consider:
|
|
19785
|
+
- Using a new variable name for the new value
|
|
19786
|
+
- Updating the original reactive source instead`
|
|
19787
|
+
);
|
|
19800
19788
|
}
|
|
19801
19789
|
if (capturedTracked && isSignal) {
|
|
19802
19790
|
return t2.expressionStatement(
|
|
@@ -19804,7 +19792,14 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19804
19792
|
);
|
|
19805
19793
|
}
|
|
19806
19794
|
if (aliasVars.has(baseName2) && !declaredVars.has(baseName2)) {
|
|
19807
|
-
throw new Error(
|
|
19795
|
+
throw new Error(
|
|
19796
|
+
`Alias reassignment is not supported for "${baseName2}".
|
|
19797
|
+
|
|
19798
|
+
"${baseName2}" was assigned from a reactive value and cannot be reassigned.
|
|
19799
|
+
Consider:
|
|
19800
|
+
- Using a new variable name for the new value
|
|
19801
|
+
- Updating the original reactive source instead`
|
|
19802
|
+
);
|
|
19808
19803
|
}
|
|
19809
19804
|
if (dependsOnTracked && !declKind && !isDestructuringTemp && !isTracked && !isSignal && instr.value.kind === "Identifier" && ctx.trackedVars.has(deSSAVarName(instr.value.name))) {
|
|
19810
19805
|
const derivedExpr = lowerAssignedValue(true);
|
|
@@ -19828,13 +19823,20 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19828
19823
|
t2.assignmentExpression(
|
|
19829
19824
|
"=",
|
|
19830
19825
|
t2.identifier(baseName2),
|
|
19831
|
-
isMemoReturningCall ? derivedExpr :
|
|
19826
|
+
isMemoReturningCall ? derivedExpr : buildDerivedMemoCall(derivedExpr)
|
|
19832
19827
|
)
|
|
19833
19828
|
);
|
|
19834
19829
|
}
|
|
19835
19830
|
if (declaredVars.has(baseName2)) {
|
|
19836
19831
|
if (aliasVars.has(baseName2)) {
|
|
19837
|
-
throw new Error(
|
|
19832
|
+
throw new Error(
|
|
19833
|
+
`Alias reassignment is not supported for "${baseName2}".
|
|
19834
|
+
|
|
19835
|
+
"${baseName2}" was assigned from a reactive value and cannot be reassigned.
|
|
19836
|
+
Consider:
|
|
19837
|
+
- Using a new variable name for the new value
|
|
19838
|
+
- Updating the original reactive source instead`
|
|
19839
|
+
);
|
|
19838
19840
|
}
|
|
19839
19841
|
if (isSignal) {
|
|
19840
19842
|
return t2.expressionStatement(
|
|
@@ -19876,7 +19878,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19876
19878
|
return t2.variableDeclaration("const", [
|
|
19877
19879
|
t2.variableDeclarator(
|
|
19878
19880
|
t2.identifier(baseName2),
|
|
19879
|
-
isMemoReturningCall ? derivedExpr :
|
|
19881
|
+
isMemoReturningCall ? derivedExpr : buildDerivedMemoCall(derivedExpr)
|
|
19880
19882
|
)
|
|
19881
19883
|
]);
|
|
19882
19884
|
}
|
|
@@ -19900,7 +19902,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19900
19902
|
return t2.variableDeclaration("const", [
|
|
19901
19903
|
t2.variableDeclarator(
|
|
19902
19904
|
t2.identifier(baseName2),
|
|
19903
|
-
isMemoReturningCall ? derivedExpr :
|
|
19905
|
+
isMemoReturningCall ? derivedExpr : buildDerivedMemoCall(derivedExpr)
|
|
19904
19906
|
)
|
|
19905
19907
|
]);
|
|
19906
19908
|
}
|
|
@@ -19920,8 +19922,6 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19920
19922
|
const inNonReactiveScope = !!(ctx.nonReactiveScopeDepth && ctx.nonReactiveScopeDepth > 0);
|
|
19921
19923
|
const shouldWrapExpr = ctx.wrapTrackedExpressions !== false && !inNonReactiveScope && (usesTracked || hasTrackedControlDep);
|
|
19922
19924
|
if (shouldWrapExpr) {
|
|
19923
|
-
ctx.helpersUsed.add("useEffect");
|
|
19924
|
-
ctx.needsCtx = true;
|
|
19925
19925
|
const depReads = [];
|
|
19926
19926
|
if (hasTrackedControlDep) {
|
|
19927
19927
|
const uniqueDeps = new Set(Array.from(controlDeps).map((dep) => deSSAVarName(dep)));
|
|
@@ -19933,12 +19933,8 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19933
19933
|
}
|
|
19934
19934
|
const loweredExpr = lowerExpressionWithDeSSA(instr.value, ctx);
|
|
19935
19935
|
const effectBody = depReads.length > 0 ? ctx.t.blockStatement([...depReads, ctx.t.expressionStatement(loweredExpr)]) : loweredExpr;
|
|
19936
|
-
|
|
19937
|
-
|
|
19938
|
-
t2.identifier("__fictCtx"),
|
|
19939
|
-
ctx.t.isBlockStatement(effectBody) ? t2.arrowFunctionExpression([], effectBody) : t2.arrowFunctionExpression([], effectBody)
|
|
19940
|
-
])
|
|
19941
|
-
);
|
|
19936
|
+
const effectFn = ctx.t.isBlockStatement(effectBody) ? t2.arrowFunctionExpression([], effectBody) : t2.arrowFunctionExpression([], effectBody);
|
|
19937
|
+
return t2.expressionStatement(buildEffectCall(ctx, t2, effectFn));
|
|
19942
19938
|
}
|
|
19943
19939
|
return t2.expressionStatement(lowerExpressionWithDeSSA(instr.value, ctx));
|
|
19944
19940
|
}
|
|
@@ -20481,6 +20477,7 @@ function createCodegenContext(t2) {
|
|
|
20481
20477
|
mutatedVars: /* @__PURE__ */ new Set(),
|
|
20482
20478
|
inRegionMemo: false,
|
|
20483
20479
|
inListRender: false,
|
|
20480
|
+
inModule: false,
|
|
20484
20481
|
nextHookSlot: HOOK_SLOT_BASE,
|
|
20485
20482
|
nonReactiveScopeDepth: 0,
|
|
20486
20483
|
inConditional: 0,
|
|
@@ -20801,7 +20798,15 @@ function detectDerivedCycles(fn, _scopeResult) {
|
|
|
20801
20798
|
if (visiting.has(node)) {
|
|
20802
20799
|
const idx = stack.indexOf(node);
|
|
20803
20800
|
const cycle = idx >= 0 ? [...stack.slice(idx), node] : [...stack, node];
|
|
20804
|
-
throw new Error(
|
|
20801
|
+
throw new Error(
|
|
20802
|
+
`Detected cyclic derived dependency: ${cycle.join(" -> ")}
|
|
20803
|
+
|
|
20804
|
+
Tip: This usually happens when derived values depend on each other in a loop.
|
|
20805
|
+
Consider:
|
|
20806
|
+
- Using untrack() to break the dependency cycle
|
|
20807
|
+
- Restructuring your derived values to avoid circular dependencies
|
|
20808
|
+
- Moving one of the values to $state if it should be independently mutable`
|
|
20809
|
+
);
|
|
20805
20810
|
}
|
|
20806
20811
|
if (visited.has(node)) return;
|
|
20807
20812
|
visiting.add(node);
|
|
@@ -20816,12 +20821,11 @@ function detectDerivedCycles(fn, _scopeResult) {
|
|
|
20816
20821
|
for (const node of graph.keys()) {
|
|
20817
20822
|
visit(node);
|
|
20818
20823
|
}
|
|
20819
|
-
|
|
20820
|
-
|
|
20821
|
-
|
|
20822
|
-
|
|
20823
|
-
|
|
20824
|
-
}
|
|
20824
|
+
debugLog(
|
|
20825
|
+
"cycles",
|
|
20826
|
+
"cycle graph",
|
|
20827
|
+
Array.from(graph.entries()).map(([k, v]) => [k, Array.from(v)])
|
|
20828
|
+
);
|
|
20825
20829
|
}
|
|
20826
20830
|
function collectExpressionIdentifiers(expr, into) {
|
|
20827
20831
|
if (!expr || typeof expr !== "object") return;
|
|
@@ -21917,22 +21921,32 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
|
|
|
21917
21921
|
return t2.identifier("undefined");
|
|
21918
21922
|
case "CallExpression": {
|
|
21919
21923
|
if (expr.callee.kind === "Identifier" && expr.callee.name === "$state") {
|
|
21924
|
+
const args = lowerCallArguments(expr.arguments);
|
|
21925
|
+
if (ctx.inModule) {
|
|
21926
|
+
ctx.helpersUsed.add("signal");
|
|
21927
|
+
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.signal), args);
|
|
21928
|
+
}
|
|
21920
21929
|
ctx.helpersUsed.add("useSignal");
|
|
21921
21930
|
ctx.needsCtx = true;
|
|
21922
21931
|
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.useSignal), [
|
|
21923
21932
|
t2.identifier("__fictCtx"),
|
|
21924
|
-
...
|
|
21933
|
+
...args
|
|
21925
21934
|
]);
|
|
21926
21935
|
}
|
|
21927
21936
|
if (expr.callee.kind === "Identifier" && expr.callee.name === "$effect") {
|
|
21937
|
+
const args = lowerCallArguments(
|
|
21938
|
+
expr.arguments,
|
|
21939
|
+
(arg) => arg.kind === "ArrowFunction" || arg.kind === "FunctionExpression" ? withNonReactiveScope(ctx, () => lowerExpression(arg, ctx)) : lowerExpression(arg, ctx)
|
|
21940
|
+
);
|
|
21941
|
+
if (ctx.inModule) {
|
|
21942
|
+
ctx.helpersUsed.add("effect");
|
|
21943
|
+
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.effect), args);
|
|
21944
|
+
}
|
|
21928
21945
|
ctx.helpersUsed.add("useEffect");
|
|
21929
21946
|
ctx.needsCtx = true;
|
|
21930
21947
|
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), [
|
|
21931
21948
|
t2.identifier("__fictCtx"),
|
|
21932
|
-
...
|
|
21933
|
-
expr.arguments,
|
|
21934
|
-
(arg) => arg.kind === "ArrowFunction" || arg.kind === "FunctionExpression" ? withNonReactiveScope(ctx, () => lowerExpression(arg, ctx)) : lowerExpression(arg, ctx)
|
|
21935
|
-
)
|
|
21949
|
+
...args
|
|
21936
21950
|
]);
|
|
21937
21951
|
}
|
|
21938
21952
|
if (expr.callee.kind === "Identifier" && expr.callee.name === "__forOf") {
|
|
@@ -22824,6 +22838,16 @@ function isExpressionReactive(expr, ctx) {
|
|
|
22824
22838
|
for (const dep of deps) {
|
|
22825
22839
|
if (ctx.trackedVars.has(dep)) return true;
|
|
22826
22840
|
}
|
|
22841
|
+
if (ctx.memoVars) {
|
|
22842
|
+
for (const dep of deps) {
|
|
22843
|
+
if (ctx.memoVars.has(dep)) return true;
|
|
22844
|
+
}
|
|
22845
|
+
}
|
|
22846
|
+
if (ctx.signalVars) {
|
|
22847
|
+
for (const dep of deps) {
|
|
22848
|
+
if (ctx.signalVars.has(dep)) return true;
|
|
22849
|
+
}
|
|
22850
|
+
}
|
|
22827
22851
|
for (const region of regionsToCheck) {
|
|
22828
22852
|
for (const dep of deps) {
|
|
22829
22853
|
if (region.declarations.has(dep) || region.dependencies.has(dep)) {
|
|
@@ -23091,8 +23115,12 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
23091
23115
|
const regionMeta = containingRegion ? regionInfoToMetadata(containingRegion) : null;
|
|
23092
23116
|
const shouldMemo = !ctx.inListRender && !(ctx.inConditional && ctx.inConditional > 0) && regionMeta ? shouldMemoizeRegion(regionMeta) : false;
|
|
23093
23117
|
if (shouldMemo) {
|
|
23094
|
-
ctx.
|
|
23095
|
-
|
|
23118
|
+
if (ctx.inModule) {
|
|
23119
|
+
ctx.helpersUsed.add("memo");
|
|
23120
|
+
} else {
|
|
23121
|
+
ctx.helpersUsed.add("useMemo");
|
|
23122
|
+
ctx.needsCtx = true;
|
|
23123
|
+
}
|
|
23096
23124
|
}
|
|
23097
23125
|
const hoistedTmplId = getOrCreateHoistedTemplate(html, ctx);
|
|
23098
23126
|
const rootId = genTemp(ctx, "root");
|
|
@@ -23366,16 +23394,15 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
23366
23394
|
statements.push(t2.returnStatement(elId));
|
|
23367
23395
|
const body = t2.blockStatement(statements);
|
|
23368
23396
|
if (shouldMemo && containingRegion) {
|
|
23369
|
-
const
|
|
23370
|
-
|
|
23371
|
-
t2.
|
|
23372
|
-
|
|
23397
|
+
const memoBody = t2.arrowFunctionExpression([], body);
|
|
23398
|
+
if (ctx.inModule) {
|
|
23399
|
+
return t2.callExpression(t2.callExpression(t2.identifier(RUNTIME_ALIASES.memo), [memoBody]), []);
|
|
23400
|
+
}
|
|
23401
|
+
const memoArgs = [t2.identifier("__fictCtx"), memoBody];
|
|
23373
23402
|
if (ctx.isComponentFn) {
|
|
23374
|
-
|
|
23375
|
-
|
|
23376
|
-
|
|
23377
|
-
memoArgs.push(t2.numericLiteral(slot));
|
|
23378
|
-
}
|
|
23403
|
+
const slot = reserveHookSlot2(ctx);
|
|
23404
|
+
if (slot >= 0) {
|
|
23405
|
+
memoArgs.push(t2.numericLiteral(slot));
|
|
23379
23406
|
}
|
|
23380
23407
|
}
|
|
23381
23408
|
return t2.callExpression(t2.callExpression(t2.identifier(RUNTIME_ALIASES.useMemo), memoArgs), []);
|
|
@@ -23435,9 +23462,9 @@ function emitHIRChildBinding(markerId, expr, statements, ctx, containingRegion)
|
|
|
23435
23462
|
emitConditionalChild(parentId, markerId, expr, statements, ctx);
|
|
23436
23463
|
return;
|
|
23437
23464
|
}
|
|
23438
|
-
if (expr.kind === "CallExpression") {
|
|
23465
|
+
if (expr.kind === "CallExpression" || expr.kind === "OptionalCallExpression") {
|
|
23439
23466
|
const callee = expr.callee;
|
|
23440
|
-
if (callee.kind === "MemberExpression" && callee.property.kind === "Identifier" && callee.property.name === "map") {
|
|
23467
|
+
if ((callee.kind === "MemberExpression" || callee.kind === "OptionalMemberExpression") && callee.property.kind === "Identifier" && callee.property.name === "map") {
|
|
23441
23468
|
emitListChild(parentId, markerId, expr, statements, ctx);
|
|
23442
23469
|
return;
|
|
23443
23470
|
}
|
|
@@ -23477,10 +23504,14 @@ function emitConditionalChild(parentId, markerId, expr, statements, ctx) {
|
|
|
23477
23504
|
ctx.helpersUsed.add("conditional");
|
|
23478
23505
|
ctx.helpersUsed.add("createElement");
|
|
23479
23506
|
ctx.helpersUsed.add("onDestroy");
|
|
23480
|
-
ctx.helpersUsed.add("toNodeArray");
|
|
23481
23507
|
let condition;
|
|
23482
23508
|
let consequent;
|
|
23483
23509
|
let alternate = null;
|
|
23510
|
+
const lowerBranch = (branch) => {
|
|
23511
|
+
const listExpr = buildListCallExpression(branch, statements, ctx);
|
|
23512
|
+
if (listExpr) return listExpr;
|
|
23513
|
+
return lowerDomExpression(branch, ctx);
|
|
23514
|
+
};
|
|
23484
23515
|
const enterConditional = () => {
|
|
23485
23516
|
ctx.inConditional = (ctx.inConditional ?? 0) + 1;
|
|
23486
23517
|
};
|
|
@@ -23490,13 +23521,13 @@ function emitConditionalChild(parentId, markerId, expr, statements, ctx) {
|
|
|
23490
23521
|
if (expr.kind === "ConditionalExpression") {
|
|
23491
23522
|
condition = lowerDomExpression(expr.test, ctx);
|
|
23492
23523
|
enterConditional();
|
|
23493
|
-
consequent =
|
|
23494
|
-
alternate =
|
|
23524
|
+
consequent = lowerBranch(expr.consequent);
|
|
23525
|
+
alternate = lowerBranch(expr.alternate);
|
|
23495
23526
|
exitConditional();
|
|
23496
23527
|
} else if (expr.kind === "LogicalExpression" && expr.operator === "&&") {
|
|
23497
23528
|
condition = lowerDomExpression(expr.left, ctx);
|
|
23498
23529
|
enterConditional();
|
|
23499
|
-
consequent =
|
|
23530
|
+
consequent = lowerBranch(expr.right);
|
|
23500
23531
|
exitConditional();
|
|
23501
23532
|
} else {
|
|
23502
23533
|
return;
|
|
@@ -23518,29 +23549,11 @@ function emitConditionalChild(parentId, markerId, expr, statements, ctx) {
|
|
|
23518
23549
|
)
|
|
23519
23550
|
])
|
|
23520
23551
|
);
|
|
23521
|
-
const markersId = genTemp(ctx, "markers");
|
|
23522
|
-
statements.push(
|
|
23523
|
-
t2.variableDeclaration("const", [
|
|
23524
|
-
t2.variableDeclarator(
|
|
23525
|
-
markersId,
|
|
23526
|
-
t2.callExpression(t2.identifier(RUNTIME_ALIASES.toNodeArray), [
|
|
23527
|
-
t2.memberExpression(bindingId, t2.identifier("marker"))
|
|
23528
|
-
])
|
|
23529
|
-
)
|
|
23530
|
-
])
|
|
23531
|
-
);
|
|
23532
|
-
const mId = genTemp(ctx, "m");
|
|
23533
23552
|
statements.push(
|
|
23534
|
-
t2.
|
|
23535
|
-
t2.
|
|
23536
|
-
|
|
23537
|
-
|
|
23538
|
-
t2.expressionStatement(
|
|
23539
|
-
t2.callExpression(t2.memberExpression(parentId, t2.identifier("insertBefore")), [
|
|
23540
|
-
mId,
|
|
23541
|
-
markerId
|
|
23542
|
-
])
|
|
23543
|
-
)
|
|
23553
|
+
t2.expressionStatement(
|
|
23554
|
+
t2.callExpression(t2.memberExpression(parentId, t2.identifier("insertBefore")), [
|
|
23555
|
+
t2.memberExpression(bindingId, t2.identifier("marker")),
|
|
23556
|
+
markerId
|
|
23544
23557
|
])
|
|
23545
23558
|
)
|
|
23546
23559
|
);
|
|
@@ -23890,10 +23903,18 @@ function applySelectorHoist(callbackExpr, itemParamName, keyParamName, statement
|
|
|
23890
23903
|
};
|
|
23891
23904
|
const visitNode = (node) => {
|
|
23892
23905
|
if (t2.isFunctionExpression(node) || t2.isArrowFunctionExpression(node)) {
|
|
23893
|
-
if (node !== callbackExpr)
|
|
23906
|
+
if (node !== callbackExpr) {
|
|
23907
|
+
if (t2.isBlockStatement(node.body)) {
|
|
23908
|
+
node.body.body.forEach((stmt) => visitNode(stmt));
|
|
23909
|
+
} else if (t2.isExpression(node.body)) {
|
|
23910
|
+
visitNode(node.body);
|
|
23911
|
+
}
|
|
23912
|
+
return;
|
|
23913
|
+
}
|
|
23894
23914
|
}
|
|
23895
|
-
if (t2.isCallExpression(node)
|
|
23896
|
-
|
|
23915
|
+
if (t2.isCallExpression(node)) {
|
|
23916
|
+
const calleeName = t2.isIdentifier(node.callee) ? node.callee.name : t2.isMemberExpression(node.callee) && t2.isIdentifier(node.callee.property) ? node.callee.property.name : null;
|
|
23917
|
+
if (calleeName === RUNTIME_ALIASES.bindClass || calleeName === "bindClass") {
|
|
23897
23918
|
const handler = node.arguments[1];
|
|
23898
23919
|
if (handler && (t2.isArrowFunctionExpression(handler) || t2.isFunctionExpression(handler))) {
|
|
23899
23920
|
rewriteInFunction(handler);
|
|
@@ -23976,20 +23997,26 @@ function applySelectorHoist(callbackExpr, itemParamName, keyParamName, statement
|
|
|
23976
23997
|
}
|
|
23977
23998
|
}
|
|
23978
23999
|
}
|
|
23979
|
-
function
|
|
24000
|
+
function buildListCallExpression(expr, statements, ctx) {
|
|
23980
24001
|
const { t: t2 } = ctx;
|
|
23981
|
-
if (expr.kind !== "CallExpression"
|
|
23982
|
-
return;
|
|
24002
|
+
if (expr.kind !== "CallExpression" && expr.kind !== "OptionalCallExpression") {
|
|
24003
|
+
return null;
|
|
24004
|
+
}
|
|
24005
|
+
if (expr.callee.kind !== "MemberExpression" && expr.callee.kind !== "OptionalMemberExpression") {
|
|
24006
|
+
return null;
|
|
23983
24007
|
}
|
|
23984
|
-
|
|
24008
|
+
if (expr.callee.property.kind !== "Identifier" || expr.callee.property.name !== "map") {
|
|
24009
|
+
return null;
|
|
24010
|
+
}
|
|
24011
|
+
const isOptional = expr.kind === "OptionalCallExpression" || expr.callee.kind === "OptionalMemberExpression" && expr.callee.optional;
|
|
24012
|
+
const arrayExprBase = lowerDomExpression(expr.callee.object, ctx);
|
|
24013
|
+
const arrayExpr = isOptional ? t2.logicalExpression("??", arrayExprBase, t2.arrayExpression([])) : arrayExprBase;
|
|
23985
24014
|
const mapCallback = expr.arguments[0];
|
|
23986
24015
|
if (!mapCallback) {
|
|
23987
24016
|
throw new Error("map callback is required");
|
|
23988
24017
|
}
|
|
23989
24018
|
const keyExpr = extractKeyFromMapCallback(mapCallback);
|
|
23990
24019
|
const isKeyed = !!keyExpr;
|
|
23991
|
-
ctx.helpersUsed.add("onDestroy");
|
|
23992
|
-
ctx.helpersUsed.add("toNodeArray");
|
|
23993
24020
|
if (isKeyed) {
|
|
23994
24021
|
ctx.helpersUsed.add("keyedList");
|
|
23995
24022
|
} else {
|
|
@@ -24017,6 +24044,7 @@ function emitListChild(parentId, markerId, expr, statements, ctx) {
|
|
|
24017
24044
|
ctx.inListRender = true;
|
|
24018
24045
|
let callbackExpr = lowerExpression(mapCallback, ctx);
|
|
24019
24046
|
ctx.inListRender = prevInListRender;
|
|
24047
|
+
const capturedKeyParamName = ctx.listKeyParamName;
|
|
24020
24048
|
ctx.listKeyExpr = prevListKeyExpr;
|
|
24021
24049
|
ctx.listItemParamName = prevListItemParamName;
|
|
24022
24050
|
ctx.listKeyParamName = prevListKeyParamName;
|
|
@@ -24054,18 +24082,17 @@ function emitListChild(parentId, markerId, expr, statements, ctx) {
|
|
|
24054
24082
|
}
|
|
24055
24083
|
}
|
|
24056
24084
|
}
|
|
24057
|
-
const listId = genTemp(ctx, "list");
|
|
24058
24085
|
if (isKeyed) {
|
|
24059
24086
|
const itemParamName = t2.isArrowFunctionExpression(callbackExpr) || t2.isFunctionExpression(callbackExpr) ? t2.isIdentifier(callbackExpr.params[0]) ? callbackExpr.params[0].name : null : null;
|
|
24060
|
-
const keyParamName = ctx.listKeyParamName ?? null;
|
|
24061
24087
|
applySelectorHoist(
|
|
24062
24088
|
callbackExpr,
|
|
24063
24089
|
itemParamName,
|
|
24064
|
-
|
|
24090
|
+
capturedKeyParamName ?? null,
|
|
24065
24091
|
statements,
|
|
24066
24092
|
ctx
|
|
24067
24093
|
);
|
|
24068
24094
|
}
|
|
24095
|
+
let listCall;
|
|
24069
24096
|
if (isKeyed && keyExpr) {
|
|
24070
24097
|
let keyExprAst = lowerExpression(keyExpr, ctx);
|
|
24071
24098
|
if (t2.isArrowFunctionExpression(callbackExpr) || t2.isFunctionExpression(callbackExpr)) {
|
|
@@ -24108,19 +24135,12 @@ function emitListChild(parentId, markerId, expr, statements, ctx) {
|
|
|
24108
24135
|
}
|
|
24109
24136
|
}
|
|
24110
24137
|
statements.push(...hoistedStatements);
|
|
24111
|
-
|
|
24112
|
-
t2.
|
|
24113
|
-
|
|
24114
|
-
|
|
24115
|
-
|
|
24116
|
-
|
|
24117
|
-
keyFn,
|
|
24118
|
-
callbackExpr,
|
|
24119
|
-
t2.booleanLiteral(hasIndexParam)
|
|
24120
|
-
])
|
|
24121
|
-
)
|
|
24122
|
-
])
|
|
24123
|
-
);
|
|
24138
|
+
listCall = t2.callExpression(t2.identifier(RUNTIME_ALIASES.keyedList), [
|
|
24139
|
+
t2.arrowFunctionExpression([], arrayExpr),
|
|
24140
|
+
keyFn,
|
|
24141
|
+
callbackExpr,
|
|
24142
|
+
t2.booleanLiteral(hasIndexParam)
|
|
24143
|
+
]);
|
|
24124
24144
|
} else {
|
|
24125
24145
|
statements.push(...hoistedStatements);
|
|
24126
24146
|
const itemParamName = t2.isArrowFunctionExpression(callbackExpr) || t2.isFunctionExpression(callbackExpr) ? t2.isIdentifier(callbackExpr.params[0]) ? callbackExpr.params[0].name : "__item" : "__item";
|
|
@@ -24130,20 +24150,23 @@ function emitListChild(parentId, markerId, expr, statements, ctx) {
|
|
|
24130
24150
|
[t2.identifier(itemParamName), t2.identifier(indexParamName)],
|
|
24131
24151
|
t2.identifier(indexParamName)
|
|
24132
24152
|
);
|
|
24133
|
-
|
|
24134
|
-
t2.
|
|
24135
|
-
|
|
24136
|
-
|
|
24137
|
-
|
|
24138
|
-
|
|
24139
|
-
keyFn,
|
|
24140
|
-
callbackExpr,
|
|
24141
|
-
t2.booleanLiteral(hasIndexParam)
|
|
24142
|
-
])
|
|
24143
|
-
)
|
|
24144
|
-
])
|
|
24145
|
-
);
|
|
24153
|
+
listCall = t2.callExpression(t2.identifier(RUNTIME_ALIASES.keyedList), [
|
|
24154
|
+
t2.arrowFunctionExpression([], arrayExpr),
|
|
24155
|
+
keyFn,
|
|
24156
|
+
callbackExpr,
|
|
24157
|
+
t2.booleanLiteral(hasIndexParam)
|
|
24158
|
+
]);
|
|
24146
24159
|
}
|
|
24160
|
+
return listCall;
|
|
24161
|
+
}
|
|
24162
|
+
function emitListChild(parentId, markerId, expr, statements, ctx) {
|
|
24163
|
+
const { t: t2 } = ctx;
|
|
24164
|
+
const listCall = buildListCallExpression(expr, statements, ctx);
|
|
24165
|
+
if (!listCall) return;
|
|
24166
|
+
ctx.helpersUsed.add("onDestroy");
|
|
24167
|
+
ctx.helpersUsed.add("toNodeArray");
|
|
24168
|
+
const listId = genTemp(ctx, "list");
|
|
24169
|
+
statements.push(t2.variableDeclaration("const", [t2.variableDeclarator(listId, listCall)]));
|
|
24147
24170
|
const markersId = genTemp(ctx, "markers");
|
|
24148
24171
|
statements.push(
|
|
24149
24172
|
t2.variableDeclaration("const", [
|
|
@@ -24498,8 +24521,14 @@ function lowerTopLevelStatementBlock(statements, ctx, t2, name = "__module_segme
|
|
|
24498
24521
|
ctx.hookReturnInfo.set(fn.name, info);
|
|
24499
24522
|
}
|
|
24500
24523
|
}
|
|
24501
|
-
const
|
|
24502
|
-
|
|
24524
|
+
const prevInModule = ctx.inModule;
|
|
24525
|
+
ctx.inModule = true;
|
|
24526
|
+
try {
|
|
24527
|
+
const lowered = generateRegionCode(fn, scopeResult, t2, ctx);
|
|
24528
|
+
return { statements: lowered, aliases: aliasVars };
|
|
24529
|
+
} finally {
|
|
24530
|
+
ctx.inModule = prevInModule;
|
|
24531
|
+
}
|
|
24503
24532
|
}
|
|
24504
24533
|
function transformControlFlowReturns(statements, ctx) {
|
|
24505
24534
|
const { t: t2 } = ctx;
|
|
@@ -24600,12 +24629,14 @@ function lowerFunctionWithRegions(fn, ctx) {
|
|
|
24600
24629
|
const prevWrapTracked = ctx.wrapTrackedExpressions;
|
|
24601
24630
|
const prevIsComponent = ctx.isComponentFn;
|
|
24602
24631
|
const prevHookResultVarMap = ctx.hookResultVarMap;
|
|
24632
|
+
const prevInModule = ctx.inModule;
|
|
24603
24633
|
const scopedTracked = new Set(ctx.trackedVars);
|
|
24604
24634
|
const shadowedParams = new Set(fn.params.map((p) => deSSAVarName(p.name)));
|
|
24605
24635
|
fn.params.forEach((p) => scopedTracked.delete(deSSAVarName(p.name)));
|
|
24606
24636
|
ctx.trackedVars = scopedTracked;
|
|
24607
24637
|
const prevNeedsCtx = ctx.needsCtx;
|
|
24608
24638
|
ctx.needsCtx = false;
|
|
24639
|
+
ctx.inModule = false;
|
|
24609
24640
|
const prevShadowed = ctx.shadowedNames;
|
|
24610
24641
|
const functionShadowed = new Set(prevShadowed ?? []);
|
|
24611
24642
|
shadowedParams.forEach((n) => functionShadowed.add(n));
|
|
@@ -24890,9 +24921,9 @@ function lowerFunctionWithRegions(fn, ctx) {
|
|
|
24890
24921
|
ctx.hookReturnInfo.set(fn.name, info);
|
|
24891
24922
|
}
|
|
24892
24923
|
}
|
|
24893
|
-
if (
|
|
24894
|
-
|
|
24895
|
-
|
|
24924
|
+
if (fn.name === "Counter") {
|
|
24925
|
+
debugLog("region", "Tracked vars for Counter", Array.from(ctx.trackedVars));
|
|
24926
|
+
debugLog("region", "Memo vars for Counter", Array.from(ctx.memoVars));
|
|
24896
24927
|
}
|
|
24897
24928
|
hookResultVars.forEach((varName) => {
|
|
24898
24929
|
const hookName = ctx.hookResultVarMap?.get(varName);
|
|
@@ -24922,6 +24953,7 @@ function lowerFunctionWithRegions(fn, ctx) {
|
|
|
24922
24953
|
ctx.noMemo = prevNoMemo;
|
|
24923
24954
|
ctx.wrapTrackedExpressions = prevWrapTracked;
|
|
24924
24955
|
ctx.hookResultVarMap = prevHookResultVarMap;
|
|
24956
|
+
ctx.inModule = prevInModule;
|
|
24925
24957
|
return null;
|
|
24926
24958
|
}
|
|
24927
24959
|
let statements;
|
|
@@ -25010,6 +25042,7 @@ function lowerFunctionWithRegions(fn, ctx) {
|
|
|
25010
25042
|
ctx.propsParamName = prevPropsParam;
|
|
25011
25043
|
ctx.propAccessorDecls = prevPropAccessors;
|
|
25012
25044
|
ctx.delegatedEventsUsed = prevDelegatedEventsUsed;
|
|
25045
|
+
ctx.inModule = prevInModule;
|
|
25013
25046
|
return funcDecl;
|
|
25014
25047
|
}
|
|
25015
25048
|
function flattenRegions(regions) {
|
|
@@ -25653,28 +25686,49 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
25653
25686
|
if (!init) return;
|
|
25654
25687
|
if (isStateCall(init, t2)) {
|
|
25655
25688
|
if (!fictImports.has("$state")) {
|
|
25656
|
-
throw varPath.buildCodeFrameError(
|
|
25689
|
+
throw varPath.buildCodeFrameError(
|
|
25690
|
+
`$state() must be imported from "fict".
|
|
25691
|
+
|
|
25692
|
+
Add this import at the top of your file:
|
|
25693
|
+
import { $state } from 'fict'`
|
|
25694
|
+
);
|
|
25657
25695
|
}
|
|
25658
25696
|
if (!t2.isIdentifier(varPath.node.id)) {
|
|
25659
25697
|
throw varPath.buildCodeFrameError(
|
|
25660
|
-
|
|
25698
|
+
`Destructuring $state is not supported.
|
|
25699
|
+
|
|
25700
|
+
Instead of: const { a, b } = $state({ a: 1, b: 2 })
|
|
25701
|
+
Use: let state = $state({ a: 1, b: 2 })
|
|
25702
|
+
const { a, b } = state // read-only aliases
|
|
25703
|
+
|
|
25704
|
+
For deep reactivity, consider using $store from 'fict'.`
|
|
25661
25705
|
);
|
|
25662
25706
|
}
|
|
25663
25707
|
const ownerComponent = varPath.getFunctionParent();
|
|
25664
25708
|
if (!ownerComponent || !isComponentOrHookDefinition(ownerComponent)) {
|
|
25665
25709
|
throw varPath.buildCodeFrameError(
|
|
25666
|
-
|
|
25710
|
+
`$state() must be declared inside a component or hook function body.
|
|
25711
|
+
|
|
25712
|
+
For module-level shared state, use one of these alternatives:
|
|
25713
|
+
\u2022 $store from 'fict' - for deep reactive objects
|
|
25714
|
+
\u2022 createSignal from 'fict/advanced' - for primitives`
|
|
25667
25715
|
);
|
|
25668
25716
|
}
|
|
25669
25717
|
stateVars.add(varPath.node.id.name);
|
|
25670
25718
|
if (isInsideLoop(varPath) || isInsideConditional(varPath)) {
|
|
25671
25719
|
throw varPath.buildCodeFrameError(
|
|
25672
|
-
|
|
25720
|
+
`$state() cannot be declared inside loops or conditionals.
|
|
25721
|
+
|
|
25722
|
+
Signals must be created at the top level of components for stable identity.
|
|
25723
|
+
Move the $state() declaration before the loop/condition.`
|
|
25673
25724
|
);
|
|
25674
25725
|
}
|
|
25675
25726
|
if (isInsideNestedFunction(varPath)) {
|
|
25676
25727
|
throw varPath.buildCodeFrameError(
|
|
25677
|
-
|
|
25728
|
+
`$state() cannot be declared inside nested functions.
|
|
25729
|
+
|
|
25730
|
+
Move the $state() declaration to the component's top level,
|
|
25731
|
+
or extract the nested logic into a custom hook (useXxx).`
|
|
25678
25732
|
);
|
|
25679
25733
|
}
|
|
25680
25734
|
} else if (t2.isIdentifier(varPath.node.id)) {
|
|
@@ -25716,43 +25770,77 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
25716
25770
|
const isVariableDeclarator = parentPath?.isVariableDeclarator() && parentPath.node.init === callPath.node;
|
|
25717
25771
|
if (!isVariableDeclarator) {
|
|
25718
25772
|
throw callPath.buildCodeFrameError(
|
|
25719
|
-
|
|
25773
|
+
`$state() must be assigned directly to a variable.
|
|
25774
|
+
|
|
25775
|
+
Correct usage:
|
|
25776
|
+
let count = $state(0)
|
|
25777
|
+
let user = $state({ name: 'Alice' })
|
|
25778
|
+
|
|
25779
|
+
For object state with deep reactivity, consider:
|
|
25780
|
+
import { $store } from 'fict'
|
|
25781
|
+
const user = $store({ name: 'Alice', address: { city: 'NYC' } })`
|
|
25720
25782
|
);
|
|
25721
25783
|
}
|
|
25722
25784
|
if (!t2.isIdentifier(parentPath.node.id)) {
|
|
25723
25785
|
throw callPath.buildCodeFrameError(
|
|
25724
|
-
|
|
25786
|
+
`Destructuring $state is not supported.
|
|
25787
|
+
|
|
25788
|
+
Instead of: const { a, b } = $state({ a: 1, b: 2 })
|
|
25789
|
+
Use: let state = $state({ a: 1, b: 2 })
|
|
25790
|
+
const { a, b } = state // read-only aliases`
|
|
25725
25791
|
);
|
|
25726
25792
|
}
|
|
25727
25793
|
const ownerComponent = callPath.getFunctionParent();
|
|
25728
25794
|
if (!ownerComponent || !isComponentOrHookDefinition(ownerComponent)) {
|
|
25729
25795
|
throw callPath.buildCodeFrameError(
|
|
25730
|
-
|
|
25796
|
+
`$state() must be declared inside a component or hook function body.
|
|
25797
|
+
|
|
25798
|
+
For module-level shared state, use one of these alternatives:
|
|
25799
|
+
\u2022 $store from 'fict' - for deep reactive objects
|
|
25800
|
+
\u2022 createSignal from 'fict/advanced' - for primitives`
|
|
25731
25801
|
);
|
|
25732
25802
|
}
|
|
25733
25803
|
if (isInsideLoop(callPath) || isInsideConditional(callPath)) {
|
|
25734
25804
|
throw callPath.buildCodeFrameError(
|
|
25735
|
-
|
|
25805
|
+
`$state() cannot be declared inside loops or conditionals.
|
|
25806
|
+
|
|
25807
|
+
Move the declaration to the top of your component.
|
|
25808
|
+
For dynamic collections, consider using $store with an array/object.`
|
|
25736
25809
|
);
|
|
25737
25810
|
}
|
|
25738
25811
|
if (isInsideNestedFunction(callPath)) {
|
|
25739
25812
|
throw callPath.buildCodeFrameError(
|
|
25740
|
-
|
|
25813
|
+
`$state() cannot be declared inside nested functions.
|
|
25814
|
+
|
|
25815
|
+
Move the declaration to the component's top level,
|
|
25816
|
+
or extract the nested logic into a custom hook (useXxx).`
|
|
25741
25817
|
);
|
|
25742
25818
|
}
|
|
25743
25819
|
}
|
|
25744
25820
|
if (isEffectCall(callPath.node, t2)) {
|
|
25745
25821
|
if (!fictImports.has("$effect")) {
|
|
25746
|
-
throw callPath.buildCodeFrameError(
|
|
25822
|
+
throw callPath.buildCodeFrameError(
|
|
25823
|
+
`$effect() must be imported from "fict".
|
|
25824
|
+
|
|
25825
|
+
Add this import at the top of your file:
|
|
25826
|
+
import { $effect } from 'fict'`
|
|
25827
|
+
);
|
|
25747
25828
|
}
|
|
25748
25829
|
if (isInsideLoop(callPath) || isInsideConditional(callPath)) {
|
|
25749
25830
|
throw callPath.buildCodeFrameError(
|
|
25750
|
-
|
|
25831
|
+
`$effect() cannot be called inside loops or conditionals.
|
|
25832
|
+
|
|
25833
|
+
Effects must be registered at the top level of components.
|
|
25834
|
+
For conditional effects, use a condition inside the effect body instead:
|
|
25835
|
+
$effect(() => { if (condition) { /* ... */ } })`
|
|
25751
25836
|
);
|
|
25752
25837
|
}
|
|
25753
25838
|
if (isInsideNestedFunction(callPath)) {
|
|
25754
25839
|
throw callPath.buildCodeFrameError(
|
|
25755
|
-
|
|
25840
|
+
`$effect() cannot be called inside nested functions.
|
|
25841
|
+
|
|
25842
|
+
Move the effect to the component's top level,
|
|
25843
|
+
or extract the nested logic into a custom hook (useXxx).`
|
|
25756
25844
|
);
|
|
25757
25845
|
}
|
|
25758
25846
|
}
|
|
@@ -25840,9 +25928,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
25840
25928
|
});
|
|
25841
25929
|
return usesState;
|
|
25842
25930
|
};
|
|
25843
|
-
|
|
25844
|
-
console.log("[fict] alias check state vars", Array.from(stateVars));
|
|
25845
|
-
}
|
|
25931
|
+
debugLog("alias", "state vars", Array.from(stateVars));
|
|
25846
25932
|
path.traverse({
|
|
25847
25933
|
Function: {
|
|
25848
25934
|
enter() {
|
|
@@ -25855,9 +25941,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
25855
25941
|
VariableDeclarator(varPath) {
|
|
25856
25942
|
const aliasSet = currentAliasSet();
|
|
25857
25943
|
if (aliasSet && t2.isIdentifier(varPath.node.id) && rhsUsesState(varPath.get("init"))) {
|
|
25858
|
-
|
|
25859
|
-
console.log("[fict] alias add from decl", varPath.node.id.name);
|
|
25860
|
-
}
|
|
25944
|
+
debugLog("alias", "add from decl", varPath.node.id.name);
|
|
25861
25945
|
aliasSet.add(varPath.node.id.name);
|
|
25862
25946
|
}
|
|
25863
25947
|
},
|
|
@@ -25868,16 +25952,12 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
25868
25952
|
const targetName = assignPath.node.left.name;
|
|
25869
25953
|
const rightPath = assignPath.get("right");
|
|
25870
25954
|
if (rhsUsesState(rightPath)) {
|
|
25871
|
-
|
|
25872
|
-
console.log("[fict] alias add from assign", targetName);
|
|
25873
|
-
}
|
|
25955
|
+
debugLog("alias", "add from assign", targetName);
|
|
25874
25956
|
aliasSet.add(targetName);
|
|
25875
25957
|
return;
|
|
25876
25958
|
}
|
|
25877
25959
|
if (aliasSet.has(targetName)) {
|
|
25878
|
-
|
|
25879
|
-
console.log("[fict] alias reassignment detected", targetName);
|
|
25880
|
-
}
|
|
25960
|
+
debugLog("alias", "reassignment detected", targetName);
|
|
25881
25961
|
throw assignPath.buildCodeFrameError(
|
|
25882
25962
|
`Alias reassignment is not supported for "${targetName}"`
|
|
25883
25963
|
);
|