@fictjs/compiler 0.0.3 → 0.0.5
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/README.md +1 -1
- package/dist/index.cjs +343 -70
- package/dist/index.js +343 -70
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -14128,6 +14128,7 @@ var RUNTIME_HELPERS = {
|
|
|
14128
14128
|
propsRest: "__fictPropsRest",
|
|
14129
14129
|
mergeProps: "mergeProps",
|
|
14130
14130
|
useProp: "useProp",
|
|
14131
|
+
runInScope: "runInScope",
|
|
14131
14132
|
createElement: "createElement",
|
|
14132
14133
|
conditional: "createConditional",
|
|
14133
14134
|
list: "createList",
|
|
@@ -14140,6 +14141,7 @@ var RUNTIME_HELPERS = {
|
|
|
14140
14141
|
bindClass: "bindClass",
|
|
14141
14142
|
bindStyle: "bindStyle",
|
|
14142
14143
|
bindEvent: "bindEvent",
|
|
14144
|
+
callEventHandler: "callEventHandler",
|
|
14143
14145
|
bindRef: "bindRef",
|
|
14144
14146
|
toNodeArray: "toNodeArray",
|
|
14145
14147
|
createKeyedListContainer: "createKeyedListContainer",
|
|
@@ -14167,6 +14169,7 @@ var RUNTIME_ALIASES = {
|
|
|
14167
14169
|
propsRest: "__fictPropsRest",
|
|
14168
14170
|
useProp: "useProp",
|
|
14169
14171
|
mergeProps: "mergeProps",
|
|
14172
|
+
runInScope: "runInScope",
|
|
14170
14173
|
createElement: "createElement",
|
|
14171
14174
|
conditional: "createConditional",
|
|
14172
14175
|
list: "createList",
|
|
@@ -14179,6 +14182,7 @@ var RUNTIME_ALIASES = {
|
|
|
14179
14182
|
bindClass: "bindClass",
|
|
14180
14183
|
bindStyle: "bindStyle",
|
|
14181
14184
|
bindEvent: "bindEvent",
|
|
14185
|
+
callEventHandler: "callEventHandler",
|
|
14182
14186
|
bindRef: "bindRef",
|
|
14183
14187
|
toNodeArray: "toNodeArray",
|
|
14184
14188
|
createKeyedListContainer: "createKeyedListContainer",
|
|
@@ -15204,7 +15208,8 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15204
15208
|
push({
|
|
15205
15209
|
kind: "Assign",
|
|
15206
15210
|
target: { kind: "Identifier", name: stmt.id.name },
|
|
15207
|
-
value: convertExpression(fnExpr)
|
|
15211
|
+
value: convertExpression(fnExpr),
|
|
15212
|
+
declarationKind: "function"
|
|
15208
15213
|
});
|
|
15209
15214
|
return bb;
|
|
15210
15215
|
}
|
|
@@ -17693,6 +17698,110 @@ function structurizeTry(ctx, block, term) {
|
|
|
17693
17698
|
}
|
|
17694
17699
|
|
|
17695
17700
|
// src/ir/regions.ts
|
|
17701
|
+
var REACTIVE_CREATORS = /* @__PURE__ */ new Set(["createEffect", "createMemo", "createSelector"]);
|
|
17702
|
+
function expressionCreatesReactive(expr) {
|
|
17703
|
+
if (expr.kind === "CallExpression" && expr.callee.kind === "Identifier") {
|
|
17704
|
+
const base = getSSABaseName(expr.callee.name);
|
|
17705
|
+
return REACTIVE_CREATORS.has(base);
|
|
17706
|
+
}
|
|
17707
|
+
return false;
|
|
17708
|
+
}
|
|
17709
|
+
function expressionContainsReactiveCreation(expr) {
|
|
17710
|
+
if (expressionCreatesReactive(expr)) return true;
|
|
17711
|
+
switch (expr.kind) {
|
|
17712
|
+
case "CallExpression":
|
|
17713
|
+
return expressionContainsReactiveCreation(expr.callee) || expr.arguments.some((arg) => expressionContainsReactiveCreation(arg));
|
|
17714
|
+
case "MemberExpression":
|
|
17715
|
+
return expressionContainsReactiveCreation(expr.object) || expressionContainsReactiveCreation(expr.property);
|
|
17716
|
+
case "BinaryExpression":
|
|
17717
|
+
case "LogicalExpression":
|
|
17718
|
+
return expressionContainsReactiveCreation(expr.left) || expressionContainsReactiveCreation(expr.right);
|
|
17719
|
+
case "UnaryExpression":
|
|
17720
|
+
return expressionContainsReactiveCreation(expr.argument);
|
|
17721
|
+
case "ConditionalExpression":
|
|
17722
|
+
return expressionContainsReactiveCreation(expr.test) || expressionContainsReactiveCreation(expr.consequent) || expressionContainsReactiveCreation(expr.alternate);
|
|
17723
|
+
case "ArrayExpression":
|
|
17724
|
+
return expr.elements.some((el) => el && expressionContainsReactiveCreation(el));
|
|
17725
|
+
case "ObjectExpression":
|
|
17726
|
+
return expr.properties.some(
|
|
17727
|
+
(prop) => prop.kind === "SpreadElement" ? expressionContainsReactiveCreation(prop.argument) : expressionContainsReactiveCreation(prop.value)
|
|
17728
|
+
);
|
|
17729
|
+
case "ArrowFunction":
|
|
17730
|
+
if (expr.isExpression) {
|
|
17731
|
+
return expressionContainsReactiveCreation(expr.body);
|
|
17732
|
+
}
|
|
17733
|
+
return Array.isArray(expr.body) ? expr.body.some(
|
|
17734
|
+
(block) => block.instructions.some((i) => instructionContainsReactiveCreation(i))
|
|
17735
|
+
) : false;
|
|
17736
|
+
case "FunctionExpression":
|
|
17737
|
+
return expr.body.some(
|
|
17738
|
+
(block) => block.instructions.some((i) => instructionContainsReactiveCreation(i))
|
|
17739
|
+
);
|
|
17740
|
+
case "AssignmentExpression":
|
|
17741
|
+
return expressionContainsReactiveCreation(expr.left) || expressionContainsReactiveCreation(expr.right);
|
|
17742
|
+
case "UpdateExpression":
|
|
17743
|
+
return expressionContainsReactiveCreation(expr.argument);
|
|
17744
|
+
case "TemplateLiteral":
|
|
17745
|
+
return expr.expressions.some((e) => expressionContainsReactiveCreation(e));
|
|
17746
|
+
case "SpreadElement":
|
|
17747
|
+
return expressionContainsReactiveCreation(expr.argument);
|
|
17748
|
+
case "AwaitExpression":
|
|
17749
|
+
return expressionContainsReactiveCreation(expr.argument);
|
|
17750
|
+
case "YieldExpression":
|
|
17751
|
+
return expr.argument ? expressionContainsReactiveCreation(expr.argument) : false;
|
|
17752
|
+
case "NewExpression":
|
|
17753
|
+
return expressionContainsReactiveCreation(expr.callee) || expr.arguments.some((arg) => expressionContainsReactiveCreation(arg));
|
|
17754
|
+
case "OptionalCallExpression":
|
|
17755
|
+
return expressionContainsReactiveCreation(expr.callee) || expr.arguments.some((arg) => expressionContainsReactiveCreation(arg));
|
|
17756
|
+
case "JSXElement":
|
|
17757
|
+
return typeof expr.tagName !== "string" && expressionContainsReactiveCreation(expr.tagName) || expr.attributes.some(
|
|
17758
|
+
(attr) => attr.isSpread ? !!attr.spreadExpr && expressionContainsReactiveCreation(attr.spreadExpr) : attr.value ? expressionContainsReactiveCreation(attr.value) : false
|
|
17759
|
+
) || expr.children.some(
|
|
17760
|
+
(child) => child.kind === "expression" ? expressionContainsReactiveCreation(child.value) : false
|
|
17761
|
+
);
|
|
17762
|
+
default:
|
|
17763
|
+
return false;
|
|
17764
|
+
}
|
|
17765
|
+
}
|
|
17766
|
+
function instructionContainsReactiveCreation(instr) {
|
|
17767
|
+
if (instr.kind === "Assign") {
|
|
17768
|
+
return expressionContainsReactiveCreation(instr.value);
|
|
17769
|
+
}
|
|
17770
|
+
if (instr.kind === "Expression") {
|
|
17771
|
+
return expressionContainsReactiveCreation(instr.value);
|
|
17772
|
+
}
|
|
17773
|
+
return false;
|
|
17774
|
+
}
|
|
17775
|
+
function instructionIsReactiveSetup(instr) {
|
|
17776
|
+
if (instr.kind === "Assign") {
|
|
17777
|
+
return expressionCreatesReactive(instr.value);
|
|
17778
|
+
}
|
|
17779
|
+
if (instr.kind === "Expression") {
|
|
17780
|
+
return expressionCreatesReactive(instr.value);
|
|
17781
|
+
}
|
|
17782
|
+
return false;
|
|
17783
|
+
}
|
|
17784
|
+
function nodeIsPureReactiveScope(node) {
|
|
17785
|
+
let found = false;
|
|
17786
|
+
const visit = (n) => {
|
|
17787
|
+
switch (n.kind) {
|
|
17788
|
+
case "instruction": {
|
|
17789
|
+
const ok = instructionIsReactiveSetup(n.instruction);
|
|
17790
|
+
if (ok && instructionContainsReactiveCreation(n.instruction)) found = true;
|
|
17791
|
+
return ok;
|
|
17792
|
+
}
|
|
17793
|
+
case "sequence":
|
|
17794
|
+
if (n.nodes.length === 0) return false;
|
|
17795
|
+
return n.nodes.every((child) => visit(child));
|
|
17796
|
+
case "block":
|
|
17797
|
+
if (n.statements.length === 0) return false;
|
|
17798
|
+
return n.statements.every((child) => visit(child));
|
|
17799
|
+
default:
|
|
17800
|
+
return false;
|
|
17801
|
+
}
|
|
17802
|
+
};
|
|
17803
|
+
return visit(node) && found;
|
|
17804
|
+
}
|
|
17696
17805
|
function generateRegions(fn, scopeResult, shapeResult = analyzeObjectShapes(fn)) {
|
|
17697
17806
|
const regions = [];
|
|
17698
17807
|
const regionsByBlock = /* @__PURE__ */ new Map();
|
|
@@ -18033,14 +18142,67 @@ function lowerNodeWithRegionContext(node, t2, ctx, declaredVars, regionCtx) {
|
|
|
18033
18142
|
case "if": {
|
|
18034
18143
|
const prevConditional = ctx.inConditional ?? 0;
|
|
18035
18144
|
ctx.inConditional = prevConditional + 1;
|
|
18036
|
-
const
|
|
18037
|
-
|
|
18145
|
+
const conseqStmts = lowerNodeWithRegionContext(
|
|
18146
|
+
node.consequent,
|
|
18147
|
+
t2,
|
|
18148
|
+
ctx,
|
|
18149
|
+
declaredVars,
|
|
18150
|
+
regionCtx
|
|
18038
18151
|
);
|
|
18039
|
-
const
|
|
18040
|
-
lowerNodeWithRegionContext(node.alternate, t2, ctx, declaredVars, regionCtx)
|
|
18041
|
-
) : null;
|
|
18152
|
+
const altStmts = node.alternate ? lowerNodeWithRegionContext(node.alternate, t2, ctx, declaredVars, regionCtx) : null;
|
|
18042
18153
|
ctx.inConditional = prevConditional;
|
|
18043
|
-
const
|
|
18154
|
+
const conseqReactiveOnly = nodeIsPureReactiveScope(node.consequent);
|
|
18155
|
+
const altReactiveOnly = node.alternate ? nodeIsPureReactiveScope(node.alternate) : false;
|
|
18156
|
+
const testExpr = lowerExpressionWithDeSSA(node.test, ctx);
|
|
18157
|
+
const unwrapTestExpr = () => {
|
|
18158
|
+
if (t2.isArrowFunctionExpression(testExpr) && testExpr.params.length === 0 && !t2.isBlockStatement(testExpr.body)) {
|
|
18159
|
+
return t2.cloneNode(testExpr.body);
|
|
18160
|
+
}
|
|
18161
|
+
return t2.cloneNode(testExpr);
|
|
18162
|
+
};
|
|
18163
|
+
const createFlagExpr = (negate = false) => {
|
|
18164
|
+
const body = unwrapTestExpr();
|
|
18165
|
+
const bodyExpr = negate ? t2.unaryExpression("!", body) : body;
|
|
18166
|
+
return t2.arrowFunctionExpression([], bodyExpr);
|
|
18167
|
+
};
|
|
18168
|
+
if (conseqReactiveOnly || altReactiveOnly) {
|
|
18169
|
+
const stmts = [];
|
|
18170
|
+
const runInScopeId = t2.identifier(RUNTIME_ALIASES.runInScope);
|
|
18171
|
+
const addScoped = (flagExpr, body) => {
|
|
18172
|
+
ctx.helpersUsed.add("runInScope");
|
|
18173
|
+
stmts.push(
|
|
18174
|
+
t2.expressionStatement(
|
|
18175
|
+
t2.callExpression(runInScopeId, [
|
|
18176
|
+
flagExpr,
|
|
18177
|
+
t2.arrowFunctionExpression([], t2.blockStatement(body))
|
|
18178
|
+
])
|
|
18179
|
+
)
|
|
18180
|
+
);
|
|
18181
|
+
};
|
|
18182
|
+
if (conseqReactiveOnly) {
|
|
18183
|
+
addScoped(createFlagExpr(false), conseqStmts);
|
|
18184
|
+
}
|
|
18185
|
+
if (altReactiveOnly && altStmts) {
|
|
18186
|
+
addScoped(createFlagExpr(true), altStmts);
|
|
18187
|
+
}
|
|
18188
|
+
const needsFallbackConseq = !conseqReactiveOnly && conseqStmts.length > 0;
|
|
18189
|
+
const needsFallbackAlt = !altReactiveOnly && altStmts && altStmts.length > 0;
|
|
18190
|
+
if (needsFallbackConseq || needsFallbackAlt) {
|
|
18191
|
+
stmts.push(
|
|
18192
|
+
t2.ifStatement(
|
|
18193
|
+
unwrapTestExpr(),
|
|
18194
|
+
needsFallbackConseq ? t2.blockStatement(conseqStmts) : t2.blockStatement([]),
|
|
18195
|
+
needsFallbackAlt && altStmts ? t2.blockStatement(altStmts) : null
|
|
18196
|
+
)
|
|
18197
|
+
);
|
|
18198
|
+
}
|
|
18199
|
+
return stmts;
|
|
18200
|
+
}
|
|
18201
|
+
const ifStmt = t2.ifStatement(
|
|
18202
|
+
testExpr,
|
|
18203
|
+
t2.blockStatement(conseqStmts),
|
|
18204
|
+
altStmts ? t2.blockStatement(altStmts) : null
|
|
18205
|
+
);
|
|
18044
18206
|
const shouldWrapEffect = ctx.wrapTrackedExpressions !== false && !ctx.inRegionMemo && expressionUsesTracked(node.test, ctx) && !statementHasEarlyExit(ifStmt, t2);
|
|
18045
18207
|
if (shouldWrapEffect) {
|
|
18046
18208
|
ctx.helpersUsed.add("useEffect");
|
|
@@ -19034,6 +19196,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19034
19196
|
if (instr.kind === "Assign") {
|
|
19035
19197
|
const ssaName = instr.target.name;
|
|
19036
19198
|
const baseName2 = deSSAVarName(ssaName);
|
|
19199
|
+
const declKindRaw = instr.declarationKind;
|
|
19037
19200
|
propagateHookResultAlias(baseName2, instr.value, ctx);
|
|
19038
19201
|
const hookMember = resolveHookMemberValue(instr.value, ctx);
|
|
19039
19202
|
if (hookMember) {
|
|
@@ -19043,9 +19206,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19043
19206
|
} else if (hookMember.kind === "memo") {
|
|
19044
19207
|
ctx.memoVars?.add(baseName2);
|
|
19045
19208
|
}
|
|
19046
|
-
|
|
19209
|
+
const declKind2 = declKindRaw && declKindRaw !== "function" ? declKindRaw : null;
|
|
19210
|
+
if (declKind2) {
|
|
19047
19211
|
declaredVars.add(baseName2);
|
|
19048
|
-
return t2.variableDeclaration(
|
|
19212
|
+
return t2.variableDeclaration(declKind2, [
|
|
19049
19213
|
t2.variableDeclarator(t2.identifier(baseName2), hookMember.member)
|
|
19050
19214
|
]);
|
|
19051
19215
|
}
|
|
@@ -19058,11 +19222,25 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19058
19222
|
t2.assignmentExpression("=", t2.identifier(baseName2), hookMember.member)
|
|
19059
19223
|
);
|
|
19060
19224
|
}
|
|
19061
|
-
const declKind =
|
|
19225
|
+
const declKind = declKindRaw && declKindRaw !== "function" ? declKindRaw : void 0;
|
|
19226
|
+
const isFunctionDecl = instr.value.kind === "FunctionExpression" && (declKindRaw === "function" || !declKindRaw && instr.value.name === baseName2);
|
|
19227
|
+
if (isFunctionDecl) {
|
|
19228
|
+
const loweredFn = lowerExpressionWithDeSSA(instr.value, ctx);
|
|
19229
|
+
if (t2.isFunctionExpression(loweredFn)) {
|
|
19230
|
+
declaredVars.add(baseName2);
|
|
19231
|
+
return t2.functionDeclaration(
|
|
19232
|
+
t2.identifier(baseName2),
|
|
19233
|
+
loweredFn.params,
|
|
19234
|
+
loweredFn.body,
|
|
19235
|
+
loweredFn.generator ?? false,
|
|
19236
|
+
loweredFn.async ?? false
|
|
19237
|
+
);
|
|
19238
|
+
}
|
|
19239
|
+
}
|
|
19062
19240
|
const isTracked = ctx.trackedVars.has(baseName2);
|
|
19063
19241
|
const isSignal = ctx.signalVars?.has(baseName2) ?? false;
|
|
19064
19242
|
const aliasVars = ctx.aliasVars ?? (ctx.aliasVars = /* @__PURE__ */ new Set());
|
|
19065
|
-
const dependsOnTracked2 = expressionUsesTracked(instr.value, ctx);
|
|
19243
|
+
const dependsOnTracked2 = expressionUsesTracked(instr.value, ctx) || (ctx.memoVars?.has(baseName2) ?? false);
|
|
19066
19244
|
const capturedTracked = ctx.externalTracked && ctx.externalTracked.has(baseName2) && !declaredVars.has(baseName2);
|
|
19067
19245
|
const isShadowDeclaration = !!declKind && declaredVars.has(baseName2);
|
|
19068
19246
|
const treatAsTracked = !isShadowDeclaration && isTracked;
|
|
@@ -19070,6 +19248,9 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19070
19248
|
const isStateCall2 = instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && instr.value.callee.name === "$state";
|
|
19071
19249
|
const inRegionMemo = ctx.inRegionMemo ?? false;
|
|
19072
19250
|
const isFunctionValue = instr.value.kind === "ArrowFunction" || instr.value.kind === "FunctionExpression";
|
|
19251
|
+
const isAccessorReturningCall = instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && ["$memo", "createMemo", "useProp"].includes(instr.value.callee.name);
|
|
19252
|
+
const isReactiveObjectCall = instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && ["mergeProps", "prop"].includes(instr.value.callee.name);
|
|
19253
|
+
const isMemoReturningCall = isAccessorReturningCall || isReactiveObjectCall;
|
|
19073
19254
|
const lowerAssignedValue = (forceAssigned = false) => lowerExpressionWithDeSSA(instr.value, ctx, forceAssigned || isFunctionValue);
|
|
19074
19255
|
const buildMemoCall = (expr) => {
|
|
19075
19256
|
const args = [
|
|
@@ -19116,7 +19297,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19116
19297
|
t2.variableDeclarator(t2.identifier(baseName2), derivedExpr)
|
|
19117
19298
|
]);
|
|
19118
19299
|
}
|
|
19119
|
-
ctx.memoVars?.add(baseName2);
|
|
19300
|
+
if (!isReactiveObjectCall) ctx.memoVars?.add(baseName2);
|
|
19120
19301
|
if (ctx.noMemo) {
|
|
19121
19302
|
return t2.variableDeclaration(normalizedDecl, [
|
|
19122
19303
|
t2.variableDeclarator(
|
|
@@ -19126,7 +19307,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19126
19307
|
]);
|
|
19127
19308
|
}
|
|
19128
19309
|
return t2.variableDeclaration(normalizedDecl, [
|
|
19129
|
-
t2.variableDeclarator(
|
|
19310
|
+
t2.variableDeclarator(
|
|
19311
|
+
t2.identifier(baseName2),
|
|
19312
|
+
isMemoReturningCall ? derivedExpr : buildMemoCall(derivedExpr)
|
|
19313
|
+
)
|
|
19130
19314
|
]);
|
|
19131
19315
|
}
|
|
19132
19316
|
}
|
|
@@ -19137,7 +19321,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19137
19321
|
t2.variableDeclarator(t2.identifier(baseName2), derivedExpr)
|
|
19138
19322
|
]);
|
|
19139
19323
|
}
|
|
19140
|
-
ctx.memoVars?.add(baseName2);
|
|
19324
|
+
if (!isReactiveObjectCall) ctx.memoVars?.add(baseName2);
|
|
19141
19325
|
if (ctx.noMemo) {
|
|
19142
19326
|
return t2.variableDeclaration(normalizedDecl, [
|
|
19143
19327
|
t2.variableDeclarator(
|
|
@@ -19147,7 +19331,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19147
19331
|
]);
|
|
19148
19332
|
}
|
|
19149
19333
|
return t2.variableDeclaration(normalizedDecl, [
|
|
19150
|
-
t2.variableDeclarator(
|
|
19334
|
+
t2.variableDeclarator(
|
|
19335
|
+
t2.identifier(baseName2),
|
|
19336
|
+
isMemoReturningCall ? derivedExpr : buildMemoCall(derivedExpr)
|
|
19337
|
+
)
|
|
19151
19338
|
]);
|
|
19152
19339
|
}
|
|
19153
19340
|
return t2.variableDeclaration(fallbackDecl, [
|
|
@@ -19205,7 +19392,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19205
19392
|
t2.variableDeclarator(t2.identifier(baseName2), derivedExpr)
|
|
19206
19393
|
]);
|
|
19207
19394
|
}
|
|
19208
|
-
ctx.memoVars?.add(baseName2);
|
|
19395
|
+
if (!isReactiveObjectCall) ctx.memoVars?.add(baseName2);
|
|
19209
19396
|
if (ctx.noMemo) {
|
|
19210
19397
|
return t2.variableDeclaration("const", [
|
|
19211
19398
|
t2.variableDeclarator(
|
|
@@ -19215,7 +19402,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19215
19402
|
]);
|
|
19216
19403
|
}
|
|
19217
19404
|
return t2.variableDeclaration("const", [
|
|
19218
|
-
t2.variableDeclarator(
|
|
19405
|
+
t2.variableDeclarator(
|
|
19406
|
+
t2.identifier(baseName2),
|
|
19407
|
+
isMemoReturningCall ? derivedExpr : buildMemoCall(derivedExpr)
|
|
19408
|
+
)
|
|
19219
19409
|
]);
|
|
19220
19410
|
}
|
|
19221
19411
|
return t2.variableDeclaration("let", [
|
|
@@ -19229,22 +19419,17 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19229
19419
|
t2.variableDeclarator(t2.identifier(baseName2), derivedExpr)
|
|
19230
19420
|
]);
|
|
19231
19421
|
}
|
|
19232
|
-
if (ctx.memoVars?.
|
|
19233
|
-
if (buildMemoCall) {
|
|
19234
|
-
console.log("Declaring memo var:", baseName2);
|
|
19235
|
-
return t2.variableDeclaration("const", [
|
|
19236
|
-
t2.variableDeclarator(t2.identifier(baseName2), buildMemoCall(derivedExpr))
|
|
19237
|
-
]);
|
|
19238
|
-
}
|
|
19239
|
-
}
|
|
19240
|
-
ctx.memoVars?.add(baseName2);
|
|
19422
|
+
if (!isReactiveObjectCall) ctx.memoVars?.add(baseName2);
|
|
19241
19423
|
if (ctx.noMemo) {
|
|
19242
19424
|
return t2.variableDeclaration("const", [
|
|
19243
19425
|
t2.variableDeclarator(t2.identifier(baseName2), t2.arrowFunctionExpression([], derivedExpr))
|
|
19244
19426
|
]);
|
|
19245
19427
|
}
|
|
19246
19428
|
return t2.variableDeclaration("const", [
|
|
19247
|
-
t2.variableDeclarator(
|
|
19429
|
+
t2.variableDeclarator(
|
|
19430
|
+
t2.identifier(baseName2),
|
|
19431
|
+
isMemoReturningCall ? derivedExpr : buildMemoCall(derivedExpr)
|
|
19432
|
+
)
|
|
19248
19433
|
]);
|
|
19249
19434
|
}
|
|
19250
19435
|
return t2.variableDeclaration("let", [
|
|
@@ -20322,7 +20507,8 @@ function collectExpressionIdentifiersDeep(expr, into, bound = /* @__PURE__ */ ne
|
|
|
20322
20507
|
case "CallExpression":
|
|
20323
20508
|
case "OptionalCallExpression": {
|
|
20324
20509
|
const isMacroCallee = expr.callee.kind === "Identifier" && (expr.callee.name === "$state" || expr.callee.name === "$effect" || expr.callee.name === "$store");
|
|
20325
|
-
|
|
20510
|
+
const isIIFE = expr.callee.kind === "ArrowFunction" || expr.callee.kind === "FunctionExpression";
|
|
20511
|
+
if (!isMacroCallee && !isIIFE) {
|
|
20326
20512
|
collectExpressionIdentifiersDeep(expr.callee, into, bound);
|
|
20327
20513
|
}
|
|
20328
20514
|
expr.arguments.forEach(
|
|
@@ -20363,73 +20549,81 @@ function collectExpressionIdentifiersDeep(expr, into, bound = /* @__PURE__ */ ne
|
|
|
20363
20549
|
);
|
|
20364
20550
|
return;
|
|
20365
20551
|
case "ArrowFunction": {
|
|
20366
|
-
const
|
|
20367
|
-
expr.params.forEach((p) => nextBound.add(deSSAVarName(p.name)));
|
|
20552
|
+
const tempSet = /* @__PURE__ */ new Set();
|
|
20368
20553
|
if (expr.isExpression && expr.body && !Array.isArray(expr.body)) {
|
|
20369
|
-
|
|
20554
|
+
collectExpressionIdentifiers(expr.body, tempSet);
|
|
20370
20555
|
} else if (Array.isArray(expr.body)) {
|
|
20371
20556
|
for (const block of expr.body) {
|
|
20372
20557
|
for (const instr of block.instructions) {
|
|
20373
20558
|
if (instr.kind === "Assign") {
|
|
20374
|
-
|
|
20559
|
+
collectExpressionIdentifiers(instr.value, tempSet);
|
|
20375
20560
|
} else if (instr.kind === "Expression") {
|
|
20376
|
-
|
|
20561
|
+
collectExpressionIdentifiers(instr.value, tempSet);
|
|
20377
20562
|
} else if (instr.kind === "Phi") {
|
|
20378
|
-
instr.sources.forEach((src) =>
|
|
20563
|
+
instr.sources.forEach((src) => tempSet.add(deSSAVarName(src.id.name)));
|
|
20379
20564
|
}
|
|
20380
20565
|
}
|
|
20381
20566
|
const term = block.terminator;
|
|
20382
20567
|
if (term.kind === "Branch") {
|
|
20383
|
-
|
|
20568
|
+
collectExpressionIdentifiers(term.test, tempSet);
|
|
20384
20569
|
} else if (term.kind === "Switch") {
|
|
20385
|
-
|
|
20570
|
+
collectExpressionIdentifiers(term.discriminant, tempSet);
|
|
20386
20571
|
term.cases.forEach((c) => {
|
|
20387
|
-
if (c.test)
|
|
20572
|
+
if (c.test) collectExpressionIdentifiers(c.test, tempSet);
|
|
20388
20573
|
});
|
|
20389
20574
|
} else if (term.kind === "ForOf") {
|
|
20390
|
-
|
|
20575
|
+
collectExpressionIdentifiers(term.iterable, tempSet);
|
|
20391
20576
|
} else if (term.kind === "ForIn") {
|
|
20392
|
-
|
|
20577
|
+
collectExpressionIdentifiers(term.object, tempSet);
|
|
20393
20578
|
} else if (term.kind === "Return" && term.argument) {
|
|
20394
|
-
|
|
20579
|
+
collectExpressionIdentifiers(term.argument, tempSet);
|
|
20395
20580
|
} else if (term.kind === "Throw") {
|
|
20396
|
-
|
|
20581
|
+
collectExpressionIdentifiers(term.argument, tempSet);
|
|
20397
20582
|
}
|
|
20398
20583
|
}
|
|
20399
20584
|
}
|
|
20585
|
+
const paramNames = new Set(expr.params.map((p) => deSSAVarName(p.name)));
|
|
20586
|
+
for (const name of bound) paramNames.add(name);
|
|
20587
|
+
for (const dep of tempSet) {
|
|
20588
|
+
if (!paramNames.has(dep)) into.add(dep);
|
|
20589
|
+
}
|
|
20400
20590
|
return;
|
|
20401
20591
|
}
|
|
20402
20592
|
case "FunctionExpression": {
|
|
20403
|
-
const
|
|
20404
|
-
expr.params.forEach((p) => nextBound.add(deSSAVarName(p.name)));
|
|
20593
|
+
const tempSet = /* @__PURE__ */ new Set();
|
|
20405
20594
|
for (const block of expr.body) {
|
|
20406
20595
|
for (const instr of block.instructions) {
|
|
20407
20596
|
if (instr.kind === "Assign") {
|
|
20408
|
-
|
|
20597
|
+
collectExpressionIdentifiers(instr.value, tempSet);
|
|
20409
20598
|
} else if (instr.kind === "Expression") {
|
|
20410
|
-
|
|
20599
|
+
collectExpressionIdentifiers(instr.value, tempSet);
|
|
20411
20600
|
} else if (instr.kind === "Phi") {
|
|
20412
|
-
instr.sources.forEach((src) =>
|
|
20601
|
+
instr.sources.forEach((src) => tempSet.add(deSSAVarName(src.id.name)));
|
|
20413
20602
|
}
|
|
20414
20603
|
}
|
|
20415
20604
|
const term = block.terminator;
|
|
20416
20605
|
if (term.kind === "Branch") {
|
|
20417
|
-
|
|
20606
|
+
collectExpressionIdentifiers(term.test, tempSet);
|
|
20418
20607
|
} else if (term.kind === "Switch") {
|
|
20419
|
-
|
|
20608
|
+
collectExpressionIdentifiers(term.discriminant, tempSet);
|
|
20420
20609
|
term.cases.forEach((c) => {
|
|
20421
|
-
if (c.test)
|
|
20610
|
+
if (c.test) collectExpressionIdentifiers(c.test, tempSet);
|
|
20422
20611
|
});
|
|
20423
20612
|
} else if (term.kind === "ForOf") {
|
|
20424
|
-
|
|
20613
|
+
collectExpressionIdentifiers(term.iterable, tempSet);
|
|
20425
20614
|
} else if (term.kind === "ForIn") {
|
|
20426
|
-
|
|
20615
|
+
collectExpressionIdentifiers(term.object, tempSet);
|
|
20427
20616
|
} else if (term.kind === "Return" && term.argument) {
|
|
20428
|
-
|
|
20617
|
+
collectExpressionIdentifiers(term.argument, tempSet);
|
|
20429
20618
|
} else if (term.kind === "Throw") {
|
|
20430
|
-
|
|
20619
|
+
collectExpressionIdentifiers(term.argument, tempSet);
|
|
20431
20620
|
}
|
|
20432
20621
|
}
|
|
20622
|
+
const paramNames = new Set(expr.params.map((p) => deSSAVarName(p.name)));
|
|
20623
|
+
for (const name of bound) paramNames.add(name);
|
|
20624
|
+
for (const dep of tempSet) {
|
|
20625
|
+
if (!paramNames.has(dep)) into.add(dep);
|
|
20626
|
+
}
|
|
20433
20627
|
return;
|
|
20434
20628
|
}
|
|
20435
20629
|
case "AssignmentExpression":
|
|
@@ -20498,6 +20692,13 @@ function getExpressionIdentifiers(expr) {
|
|
|
20498
20692
|
}
|
|
20499
20693
|
return deps;
|
|
20500
20694
|
}
|
|
20695
|
+
function getExpressionIdentifiersDeep(expr) {
|
|
20696
|
+
const deps = /* @__PURE__ */ new Set();
|
|
20697
|
+
if (expr) {
|
|
20698
|
+
collectExpressionIdentifiersDeep(expr, deps);
|
|
20699
|
+
}
|
|
20700
|
+
return deps;
|
|
20701
|
+
}
|
|
20501
20702
|
function buildControlDependencyMap(fn) {
|
|
20502
20703
|
const depsByInstruction = /* @__PURE__ */ new Map();
|
|
20503
20704
|
let structured;
|
|
@@ -20624,7 +20825,7 @@ function computeReactiveAccessors(fn, ctx) {
|
|
|
20624
20825
|
for (const instr of block.instructions) {
|
|
20625
20826
|
if (instr.kind === "Assign") {
|
|
20626
20827
|
const target = deSSAVarName(instr.target.name);
|
|
20627
|
-
const dataDeps =
|
|
20828
|
+
const dataDeps = getExpressionIdentifiersDeep(instr.value);
|
|
20628
20829
|
addDepsToTarget(target, dataDeps, dataDepsByTarget);
|
|
20629
20830
|
const controlDeps = controlDepsByInstr.get(instr) ?? /* @__PURE__ */ new Set();
|
|
20630
20831
|
addDepsToTarget(target, controlDeps, controlDepsByTarget);
|
|
@@ -20685,7 +20886,7 @@ function computeReactiveAccessors(fn, ctx) {
|
|
|
20685
20886
|
if (instr.kind === "Assign") {
|
|
20686
20887
|
const target = deSSAVarName(instr.target.name);
|
|
20687
20888
|
if (isFunctionVar(target)) continue;
|
|
20688
|
-
const dataDeps =
|
|
20889
|
+
const dataDeps = getExpressionIdentifiersDeep(instr.value);
|
|
20689
20890
|
const controlDepsForInstr = controlDepsByInstr.get(instr) ?? /* @__PURE__ */ new Set();
|
|
20690
20891
|
const hasDataDep = Array.from(dataDeps).some((dep) => tracked.has(dep));
|
|
20691
20892
|
const hasControlDep = Array.from(controlDepsForInstr).some((dep) => tracked.has(dep));
|
|
@@ -20695,7 +20896,8 @@ function computeReactiveAccessors(fn, ctx) {
|
|
|
20695
20896
|
tracked.add(target);
|
|
20696
20897
|
changed = true;
|
|
20697
20898
|
}
|
|
20698
|
-
|
|
20899
|
+
const isReactiveObjectCall = instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && ["mergeProps", "prop"].includes(instr.value.callee.name);
|
|
20900
|
+
if (hasDataDep && !isSignal(target) && !isStore(target) && !isReactiveObjectCall) {
|
|
20699
20901
|
memo.add(target);
|
|
20700
20902
|
}
|
|
20701
20903
|
} else if (instr.kind === "Phi") {
|
|
@@ -20783,6 +20985,20 @@ function lowerInstruction(instr, ctx) {
|
|
|
20783
20985
|
const { t: t2 } = ctx;
|
|
20784
20986
|
if (instr.kind === "Assign") {
|
|
20785
20987
|
const baseName2 = deSSAVarName(instr.target.name);
|
|
20988
|
+
const isFunctionDecl = instr.value.kind === "FunctionExpression" && (instr.declarationKind === "function" || !instr.declarationKind && instr.value.name === baseName2);
|
|
20989
|
+
if (isFunctionDecl) {
|
|
20990
|
+
const loweredFn = lowerExpression(instr.value, ctx);
|
|
20991
|
+
if (t2.isFunctionExpression(loweredFn)) {
|
|
20992
|
+
return t2.functionDeclaration(
|
|
20993
|
+
t2.identifier(baseName2),
|
|
20994
|
+
loweredFn.params,
|
|
20995
|
+
loweredFn.body,
|
|
20996
|
+
loweredFn.generator ?? false,
|
|
20997
|
+
loweredFn.async ?? false
|
|
20998
|
+
);
|
|
20999
|
+
}
|
|
21000
|
+
}
|
|
21001
|
+
const declKind = instr.declarationKind === "function" ? void 0 : instr.declarationKind;
|
|
20786
21002
|
propagateHookResultAlias(baseName2, instr.value, ctx);
|
|
20787
21003
|
const hookMember = resolveHookMemberValue(instr.value, ctx);
|
|
20788
21004
|
if (hookMember) {
|
|
@@ -20792,8 +21008,8 @@ function lowerInstruction(instr, ctx) {
|
|
|
20792
21008
|
} else if (hookMember.kind === "memo") {
|
|
20793
21009
|
ctx.memoVars?.add(baseName2);
|
|
20794
21010
|
}
|
|
20795
|
-
if (
|
|
20796
|
-
return t2.variableDeclaration(
|
|
21011
|
+
if (declKind) {
|
|
21012
|
+
return t2.variableDeclaration(declKind, [
|
|
20797
21013
|
t2.variableDeclarator(t2.identifier(baseName2), hookMember.member)
|
|
20798
21014
|
]);
|
|
20799
21015
|
}
|
|
@@ -21192,6 +21408,13 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21192
21408
|
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.mergeProps), args);
|
|
21193
21409
|
}
|
|
21194
21410
|
const isIIFE = (expr.callee.kind === "ArrowFunction" || expr.callee.kind === "FunctionExpression") && expr.arguments.length === 0 && expr.callee.params.length === 0;
|
|
21411
|
+
const calleeName = expr.callee.kind === "Identifier" ? deSSAVarName(expr.callee.name) : null;
|
|
21412
|
+
const calleeIsMemoAccessor = !!calleeName && ctx.memoVars?.has(calleeName);
|
|
21413
|
+
const calleeIsSignalLike = !!calleeName && (ctx.signalVars?.has(calleeName) || ctx.storeVars?.has(calleeName));
|
|
21414
|
+
if (calleeIsMemoAccessor && !calleeIsSignalLike && expr.arguments.length > 0) {
|
|
21415
|
+
const loweredArgs = expr.arguments.map((a) => lowerExpression(a, ctx));
|
|
21416
|
+
return t2.callExpression(t2.callExpression(t2.identifier(calleeName), []), loweredArgs);
|
|
21417
|
+
}
|
|
21195
21418
|
const lowerCallee = () => isIIFE ? withNonReactiveScope(ctx, () => lowerExpression(expr.callee, ctx)) : lowerExpression(expr.callee, ctx);
|
|
21196
21419
|
return t2.callExpression(
|
|
21197
21420
|
lowerCallee(),
|
|
@@ -21544,11 +21767,12 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21544
21767
|
return t2.identifier("undefined");
|
|
21545
21768
|
}
|
|
21546
21769
|
}
|
|
21547
|
-
function lowerDomExpression(expr, ctx, region) {
|
|
21770
|
+
function lowerDomExpression(expr, ctx, region, options) {
|
|
21548
21771
|
let lowered = lowerExpression(expr, ctx);
|
|
21549
|
-
|
|
21772
|
+
const skipHookAccessors = options?.skipHookAccessors ?? false;
|
|
21773
|
+
if (!skipHookAccessors && ctx.t.isMemberExpression(lowered) && ctx.t.isIdentifier(lowered.object) && ctx.hookResultVarMap?.has(deSSAVarName(lowered.object.name))) {
|
|
21550
21774
|
lowered = ctx.t.callExpression(lowered, []);
|
|
21551
|
-
} else if (ctx.t.isIdentifier(lowered)) {
|
|
21775
|
+
} else if (!skipHookAccessors && ctx.t.isIdentifier(lowered)) {
|
|
21552
21776
|
const hookName = ctx.hookResultVarMap?.get(deSSAVarName(lowered.name));
|
|
21553
21777
|
if (hookName) {
|
|
21554
21778
|
const info = getHookReturnInfo(hookName, ctx);
|
|
@@ -21557,7 +21781,9 @@ function lowerDomExpression(expr, ctx, region) {
|
|
|
21557
21781
|
}
|
|
21558
21782
|
}
|
|
21559
21783
|
}
|
|
21560
|
-
return applyRegionMetadataToExpression(lowered, ctx, region
|
|
21784
|
+
return applyRegionMetadataToExpression(lowered, ctx, region, {
|
|
21785
|
+
skipRootOverride: options?.skipRegionRootOverride
|
|
21786
|
+
});
|
|
21561
21787
|
}
|
|
21562
21788
|
function lowerJSXChildNonFineGrained(child, ctx) {
|
|
21563
21789
|
const { t: t2 } = ctx;
|
|
@@ -21766,12 +21992,13 @@ function getDependencyPathFromNode(node, t2) {
|
|
|
21766
21992
|
}
|
|
21767
21993
|
return null;
|
|
21768
21994
|
}
|
|
21769
|
-
function applyRegionMetadataToExpression(expr, ctx, regionOverride) {
|
|
21995
|
+
function applyRegionMetadataToExpression(expr, ctx, regionOverride, options) {
|
|
21770
21996
|
if (ctx.inReturn && ctx.currentFnIsHook) {
|
|
21771
21997
|
return expr;
|
|
21772
21998
|
}
|
|
21773
21999
|
const region = regionOverride ?? ctx.currentRegion;
|
|
21774
22000
|
if (!region) return expr;
|
|
22001
|
+
const skipRootOverride = options?.skipRootOverride ?? false;
|
|
21775
22002
|
const metadata = regionInfoToMetadata(region);
|
|
21776
22003
|
const state = {};
|
|
21777
22004
|
applyRegionMetadata(state, {
|
|
@@ -21824,7 +22051,7 @@ function applyRegionMetadataToExpression(expr, ctx, regionOverride) {
|
|
|
21824
22051
|
if (Object.keys(overrides).length === 0) {
|
|
21825
22052
|
return expr;
|
|
21826
22053
|
}
|
|
21827
|
-
if (ctx.t.isIdentifier(expr)) {
|
|
22054
|
+
if (!skipRootOverride && ctx.t.isIdentifier(expr)) {
|
|
21828
22055
|
const key = normalizeDependencyKey2(expr.name);
|
|
21829
22056
|
const direct = overrides[key] ?? overrides[expr.name];
|
|
21830
22057
|
if (direct) {
|
|
@@ -21832,10 +22059,10 @@ function applyRegionMetadataToExpression(expr, ctx, regionOverride) {
|
|
|
21832
22059
|
}
|
|
21833
22060
|
}
|
|
21834
22061
|
const cloned = ctx.t.cloneNode(expr, true);
|
|
21835
|
-
replaceIdentifiersWithOverrides(cloned, overrides, ctx.t);
|
|
22062
|
+
replaceIdentifiersWithOverrides(cloned, overrides, ctx.t, void 0, void 0, skipRootOverride);
|
|
21836
22063
|
return cloned;
|
|
21837
22064
|
}
|
|
21838
|
-
function replaceIdentifiersWithOverrides(node, overrides, t2, parentKind, parentKey) {
|
|
22065
|
+
function replaceIdentifiersWithOverrides(node, overrides, t2, parentKind, parentKey, skipCurrentNode = false) {
|
|
21839
22066
|
const isCallTarget = parentKey === "callee" && (parentKind === "CallExpression" || parentKind === "OptionalCallExpression");
|
|
21840
22067
|
const collectParamNames = (params) => {
|
|
21841
22068
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -21871,7 +22098,7 @@ function replaceIdentifiersWithOverrides(node, overrides, t2, parentKind, parent
|
|
|
21871
22098
|
params.forEach((p) => visitPattern(p));
|
|
21872
22099
|
return names;
|
|
21873
22100
|
};
|
|
21874
|
-
if (t2.isMemberExpression(node) || t2.isOptionalMemberExpression(node)) {
|
|
22101
|
+
if (!skipCurrentNode && (t2.isMemberExpression(node) || t2.isOptionalMemberExpression(node))) {
|
|
21875
22102
|
const path = getDependencyPathFromNode(node, t2);
|
|
21876
22103
|
const normalized = path ? normalizeDependencyKey2(path) : null;
|
|
21877
22104
|
const override = normalized && overrides[normalized] || (path ? overrides[path] : void 0);
|
|
@@ -21881,7 +22108,7 @@ function replaceIdentifiersWithOverrides(node, overrides, t2, parentKind, parent
|
|
|
21881
22108
|
return;
|
|
21882
22109
|
}
|
|
21883
22110
|
}
|
|
21884
|
-
if (t2.isIdentifier(node)) {
|
|
22111
|
+
if (!skipCurrentNode && t2.isIdentifier(node)) {
|
|
21885
22112
|
const key = normalizeDependencyKey2(node.name);
|
|
21886
22113
|
const override = overrides[key] ?? overrides[node.name];
|
|
21887
22114
|
if (override && !isCallTarget) {
|
|
@@ -21926,7 +22153,8 @@ function replaceIdentifiersWithOverrides(node, overrides, t2, parentKind, parent
|
|
|
21926
22153
|
overrides,
|
|
21927
22154
|
t2,
|
|
21928
22155
|
node.type,
|
|
21929
|
-
key
|
|
22156
|
+
key,
|
|
22157
|
+
false
|
|
21930
22158
|
);
|
|
21931
22159
|
}
|
|
21932
22160
|
}
|
|
@@ -22355,7 +22583,10 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
22355
22583
|
const shouldWrapHandler = isExpressionReactive(binding.expr, ctx);
|
|
22356
22584
|
const prevWrapTracked = ctx.wrapTrackedExpressions;
|
|
22357
22585
|
ctx.wrapTrackedExpressions = false;
|
|
22358
|
-
const valueExpr = lowerDomExpression(binding.expr, ctx, containingRegion
|
|
22586
|
+
const valueExpr = lowerDomExpression(binding.expr, ctx, containingRegion, {
|
|
22587
|
+
skipHookAccessors: true,
|
|
22588
|
+
skipRegionRootOverride: true
|
|
22589
|
+
});
|
|
22359
22590
|
ctx.wrapTrackedExpressions = prevWrapTracked;
|
|
22360
22591
|
const eventParam = t2.identifier("_e");
|
|
22361
22592
|
const isFn = t2.isArrowFunctionExpression(valueExpr) || t2.isFunctionExpression(valueExpr);
|
|
@@ -24081,6 +24312,9 @@ function isInsideNestedFunction(path) {
|
|
|
24081
24312
|
}
|
|
24082
24313
|
return false;
|
|
24083
24314
|
}
|
|
24315
|
+
function isInsideJSX(path) {
|
|
24316
|
+
return !!path.findParent((p) => p.isJSXElement?.() || p.isJSXFragment?.());
|
|
24317
|
+
}
|
|
24084
24318
|
function emitWarning(node, code, message, options, fileName) {
|
|
24085
24319
|
if (!options.onWarn) return;
|
|
24086
24320
|
const loc = node.loc?.start;
|
|
@@ -24178,6 +24412,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24178
24412
|
const root = getRootIdentifier(expr, t2);
|
|
24179
24413
|
return !!(root && stateVars.has(root.name));
|
|
24180
24414
|
};
|
|
24415
|
+
const reactiveNames = /* @__PURE__ */ new Set([...stateVars, ...derivedVars]);
|
|
24181
24416
|
programPath.traverse({
|
|
24182
24417
|
AssignmentExpression(path) {
|
|
24183
24418
|
const { left } = path.node;
|
|
@@ -24240,6 +24475,35 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24240
24475
|
);
|
|
24241
24476
|
}
|
|
24242
24477
|
},
|
|
24478
|
+
Function(path) {
|
|
24479
|
+
const captured = /* @__PURE__ */ new Set();
|
|
24480
|
+
path.traverse(
|
|
24481
|
+
{
|
|
24482
|
+
Function(inner) {
|
|
24483
|
+
if (inner === path) return;
|
|
24484
|
+
inner.skip();
|
|
24485
|
+
},
|
|
24486
|
+
Identifier(idPath) {
|
|
24487
|
+
const name = idPath.node.name;
|
|
24488
|
+
if (!reactiveNames.has(name)) return;
|
|
24489
|
+
const binding = idPath.scope.getBinding(name);
|
|
24490
|
+
if (!binding) return;
|
|
24491
|
+
if (binding.scope === idPath.scope || binding.scope === path.scope) return;
|
|
24492
|
+
captured.add(name);
|
|
24493
|
+
}
|
|
24494
|
+
},
|
|
24495
|
+
{}
|
|
24496
|
+
);
|
|
24497
|
+
if (captured.size > 0) {
|
|
24498
|
+
emitWarning(
|
|
24499
|
+
path.node,
|
|
24500
|
+
"FICT-R005",
|
|
24501
|
+
`Function captures reactive variable(s): ${Array.from(captured).join(", ")}. Pass them as parameters or memoize explicitly to avoid hidden dependencies.`,
|
|
24502
|
+
options,
|
|
24503
|
+
fileName
|
|
24504
|
+
);
|
|
24505
|
+
}
|
|
24506
|
+
},
|
|
24243
24507
|
CallExpression(path) {
|
|
24244
24508
|
if (t2.isIdentifier(path.node.callee, { name: "$effect" })) {
|
|
24245
24509
|
const argPath = path.get("arguments.0");
|
|
@@ -24561,6 +24825,15 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24561
24825
|
}
|
|
24562
24826
|
const callee = callPath.node.callee;
|
|
24563
24827
|
const calleeId = t2.isIdentifier(callee) ? callee.name : null;
|
|
24828
|
+
if (calleeId && (calleeId === "createEffect" || calleeId === "createMemo" || calleeId === "createSelector") && fictImports.has(calleeId) && (isInsideLoop(callPath) || isInsideConditional(callPath)) && !isInsideJSX(callPath)) {
|
|
24829
|
+
emitWarning(
|
|
24830
|
+
callPath.node,
|
|
24831
|
+
"FICT-R004",
|
|
24832
|
+
"Reactive creation inside non-JSX control flow will not auto-dispose; wrap it in createScope/runInScope or move it into JSX-managed regions.",
|
|
24833
|
+
options,
|
|
24834
|
+
fileName
|
|
24835
|
+
);
|
|
24836
|
+
}
|
|
24564
24837
|
const allowedStateCallees = /* @__PURE__ */ new Set([
|
|
24565
24838
|
"$effect",
|
|
24566
24839
|
"$memo",
|