@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.cjs
CHANGED
|
@@ -14140,6 +14140,7 @@ var RUNTIME_HELPERS = {
|
|
|
14140
14140
|
propsRest: "__fictPropsRest",
|
|
14141
14141
|
mergeProps: "mergeProps",
|
|
14142
14142
|
useProp: "useProp",
|
|
14143
|
+
runInScope: "runInScope",
|
|
14143
14144
|
createElement: "createElement",
|
|
14144
14145
|
conditional: "createConditional",
|
|
14145
14146
|
list: "createList",
|
|
@@ -14152,6 +14153,7 @@ var RUNTIME_HELPERS = {
|
|
|
14152
14153
|
bindClass: "bindClass",
|
|
14153
14154
|
bindStyle: "bindStyle",
|
|
14154
14155
|
bindEvent: "bindEvent",
|
|
14156
|
+
callEventHandler: "callEventHandler",
|
|
14155
14157
|
bindRef: "bindRef",
|
|
14156
14158
|
toNodeArray: "toNodeArray",
|
|
14157
14159
|
createKeyedListContainer: "createKeyedListContainer",
|
|
@@ -14179,6 +14181,7 @@ var RUNTIME_ALIASES = {
|
|
|
14179
14181
|
propsRest: "__fictPropsRest",
|
|
14180
14182
|
useProp: "useProp",
|
|
14181
14183
|
mergeProps: "mergeProps",
|
|
14184
|
+
runInScope: "runInScope",
|
|
14182
14185
|
createElement: "createElement",
|
|
14183
14186
|
conditional: "createConditional",
|
|
14184
14187
|
list: "createList",
|
|
@@ -14191,6 +14194,7 @@ var RUNTIME_ALIASES = {
|
|
|
14191
14194
|
bindClass: "bindClass",
|
|
14192
14195
|
bindStyle: "bindStyle",
|
|
14193
14196
|
bindEvent: "bindEvent",
|
|
14197
|
+
callEventHandler: "callEventHandler",
|
|
14194
14198
|
bindRef: "bindRef",
|
|
14195
14199
|
toNodeArray: "toNodeArray",
|
|
14196
14200
|
createKeyedListContainer: "createKeyedListContainer",
|
|
@@ -15216,7 +15220,8 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15216
15220
|
push({
|
|
15217
15221
|
kind: "Assign",
|
|
15218
15222
|
target: { kind: "Identifier", name: stmt.id.name },
|
|
15219
|
-
value: convertExpression(fnExpr)
|
|
15223
|
+
value: convertExpression(fnExpr),
|
|
15224
|
+
declarationKind: "function"
|
|
15220
15225
|
});
|
|
15221
15226
|
return bb;
|
|
15222
15227
|
}
|
|
@@ -17705,6 +17710,110 @@ function structurizeTry(ctx, block, term) {
|
|
|
17705
17710
|
}
|
|
17706
17711
|
|
|
17707
17712
|
// src/ir/regions.ts
|
|
17713
|
+
var REACTIVE_CREATORS = /* @__PURE__ */ new Set(["createEffect", "createMemo", "createSelector"]);
|
|
17714
|
+
function expressionCreatesReactive(expr) {
|
|
17715
|
+
if (expr.kind === "CallExpression" && expr.callee.kind === "Identifier") {
|
|
17716
|
+
const base = getSSABaseName(expr.callee.name);
|
|
17717
|
+
return REACTIVE_CREATORS.has(base);
|
|
17718
|
+
}
|
|
17719
|
+
return false;
|
|
17720
|
+
}
|
|
17721
|
+
function expressionContainsReactiveCreation(expr) {
|
|
17722
|
+
if (expressionCreatesReactive(expr)) return true;
|
|
17723
|
+
switch (expr.kind) {
|
|
17724
|
+
case "CallExpression":
|
|
17725
|
+
return expressionContainsReactiveCreation(expr.callee) || expr.arguments.some((arg) => expressionContainsReactiveCreation(arg));
|
|
17726
|
+
case "MemberExpression":
|
|
17727
|
+
return expressionContainsReactiveCreation(expr.object) || expressionContainsReactiveCreation(expr.property);
|
|
17728
|
+
case "BinaryExpression":
|
|
17729
|
+
case "LogicalExpression":
|
|
17730
|
+
return expressionContainsReactiveCreation(expr.left) || expressionContainsReactiveCreation(expr.right);
|
|
17731
|
+
case "UnaryExpression":
|
|
17732
|
+
return expressionContainsReactiveCreation(expr.argument);
|
|
17733
|
+
case "ConditionalExpression":
|
|
17734
|
+
return expressionContainsReactiveCreation(expr.test) || expressionContainsReactiveCreation(expr.consequent) || expressionContainsReactiveCreation(expr.alternate);
|
|
17735
|
+
case "ArrayExpression":
|
|
17736
|
+
return expr.elements.some((el) => el && expressionContainsReactiveCreation(el));
|
|
17737
|
+
case "ObjectExpression":
|
|
17738
|
+
return expr.properties.some(
|
|
17739
|
+
(prop) => prop.kind === "SpreadElement" ? expressionContainsReactiveCreation(prop.argument) : expressionContainsReactiveCreation(prop.value)
|
|
17740
|
+
);
|
|
17741
|
+
case "ArrowFunction":
|
|
17742
|
+
if (expr.isExpression) {
|
|
17743
|
+
return expressionContainsReactiveCreation(expr.body);
|
|
17744
|
+
}
|
|
17745
|
+
return Array.isArray(expr.body) ? expr.body.some(
|
|
17746
|
+
(block) => block.instructions.some((i) => instructionContainsReactiveCreation(i))
|
|
17747
|
+
) : false;
|
|
17748
|
+
case "FunctionExpression":
|
|
17749
|
+
return expr.body.some(
|
|
17750
|
+
(block) => block.instructions.some((i) => instructionContainsReactiveCreation(i))
|
|
17751
|
+
);
|
|
17752
|
+
case "AssignmentExpression":
|
|
17753
|
+
return expressionContainsReactiveCreation(expr.left) || expressionContainsReactiveCreation(expr.right);
|
|
17754
|
+
case "UpdateExpression":
|
|
17755
|
+
return expressionContainsReactiveCreation(expr.argument);
|
|
17756
|
+
case "TemplateLiteral":
|
|
17757
|
+
return expr.expressions.some((e) => expressionContainsReactiveCreation(e));
|
|
17758
|
+
case "SpreadElement":
|
|
17759
|
+
return expressionContainsReactiveCreation(expr.argument);
|
|
17760
|
+
case "AwaitExpression":
|
|
17761
|
+
return expressionContainsReactiveCreation(expr.argument);
|
|
17762
|
+
case "YieldExpression":
|
|
17763
|
+
return expr.argument ? expressionContainsReactiveCreation(expr.argument) : false;
|
|
17764
|
+
case "NewExpression":
|
|
17765
|
+
return expressionContainsReactiveCreation(expr.callee) || expr.arguments.some((arg) => expressionContainsReactiveCreation(arg));
|
|
17766
|
+
case "OptionalCallExpression":
|
|
17767
|
+
return expressionContainsReactiveCreation(expr.callee) || expr.arguments.some((arg) => expressionContainsReactiveCreation(arg));
|
|
17768
|
+
case "JSXElement":
|
|
17769
|
+
return typeof expr.tagName !== "string" && expressionContainsReactiveCreation(expr.tagName) || expr.attributes.some(
|
|
17770
|
+
(attr) => attr.isSpread ? !!attr.spreadExpr && expressionContainsReactiveCreation(attr.spreadExpr) : attr.value ? expressionContainsReactiveCreation(attr.value) : false
|
|
17771
|
+
) || expr.children.some(
|
|
17772
|
+
(child) => child.kind === "expression" ? expressionContainsReactiveCreation(child.value) : false
|
|
17773
|
+
);
|
|
17774
|
+
default:
|
|
17775
|
+
return false;
|
|
17776
|
+
}
|
|
17777
|
+
}
|
|
17778
|
+
function instructionContainsReactiveCreation(instr) {
|
|
17779
|
+
if (instr.kind === "Assign") {
|
|
17780
|
+
return expressionContainsReactiveCreation(instr.value);
|
|
17781
|
+
}
|
|
17782
|
+
if (instr.kind === "Expression") {
|
|
17783
|
+
return expressionContainsReactiveCreation(instr.value);
|
|
17784
|
+
}
|
|
17785
|
+
return false;
|
|
17786
|
+
}
|
|
17787
|
+
function instructionIsReactiveSetup(instr) {
|
|
17788
|
+
if (instr.kind === "Assign") {
|
|
17789
|
+
return expressionCreatesReactive(instr.value);
|
|
17790
|
+
}
|
|
17791
|
+
if (instr.kind === "Expression") {
|
|
17792
|
+
return expressionCreatesReactive(instr.value);
|
|
17793
|
+
}
|
|
17794
|
+
return false;
|
|
17795
|
+
}
|
|
17796
|
+
function nodeIsPureReactiveScope(node) {
|
|
17797
|
+
let found = false;
|
|
17798
|
+
const visit = (n) => {
|
|
17799
|
+
switch (n.kind) {
|
|
17800
|
+
case "instruction": {
|
|
17801
|
+
const ok = instructionIsReactiveSetup(n.instruction);
|
|
17802
|
+
if (ok && instructionContainsReactiveCreation(n.instruction)) found = true;
|
|
17803
|
+
return ok;
|
|
17804
|
+
}
|
|
17805
|
+
case "sequence":
|
|
17806
|
+
if (n.nodes.length === 0) return false;
|
|
17807
|
+
return n.nodes.every((child) => visit(child));
|
|
17808
|
+
case "block":
|
|
17809
|
+
if (n.statements.length === 0) return false;
|
|
17810
|
+
return n.statements.every((child) => visit(child));
|
|
17811
|
+
default:
|
|
17812
|
+
return false;
|
|
17813
|
+
}
|
|
17814
|
+
};
|
|
17815
|
+
return visit(node) && found;
|
|
17816
|
+
}
|
|
17708
17817
|
function generateRegions(fn, scopeResult, shapeResult = analyzeObjectShapes(fn)) {
|
|
17709
17818
|
const regions = [];
|
|
17710
17819
|
const regionsByBlock = /* @__PURE__ */ new Map();
|
|
@@ -18045,14 +18154,67 @@ function lowerNodeWithRegionContext(node, t2, ctx, declaredVars, regionCtx) {
|
|
|
18045
18154
|
case "if": {
|
|
18046
18155
|
const prevConditional = ctx.inConditional ?? 0;
|
|
18047
18156
|
ctx.inConditional = prevConditional + 1;
|
|
18048
|
-
const
|
|
18049
|
-
|
|
18157
|
+
const conseqStmts = lowerNodeWithRegionContext(
|
|
18158
|
+
node.consequent,
|
|
18159
|
+
t2,
|
|
18160
|
+
ctx,
|
|
18161
|
+
declaredVars,
|
|
18162
|
+
regionCtx
|
|
18050
18163
|
);
|
|
18051
|
-
const
|
|
18052
|
-
lowerNodeWithRegionContext(node.alternate, t2, ctx, declaredVars, regionCtx)
|
|
18053
|
-
) : null;
|
|
18164
|
+
const altStmts = node.alternate ? lowerNodeWithRegionContext(node.alternate, t2, ctx, declaredVars, regionCtx) : null;
|
|
18054
18165
|
ctx.inConditional = prevConditional;
|
|
18055
|
-
const
|
|
18166
|
+
const conseqReactiveOnly = nodeIsPureReactiveScope(node.consequent);
|
|
18167
|
+
const altReactiveOnly = node.alternate ? nodeIsPureReactiveScope(node.alternate) : false;
|
|
18168
|
+
const testExpr = lowerExpressionWithDeSSA(node.test, ctx);
|
|
18169
|
+
const unwrapTestExpr = () => {
|
|
18170
|
+
if (t2.isArrowFunctionExpression(testExpr) && testExpr.params.length === 0 && !t2.isBlockStatement(testExpr.body)) {
|
|
18171
|
+
return t2.cloneNode(testExpr.body);
|
|
18172
|
+
}
|
|
18173
|
+
return t2.cloneNode(testExpr);
|
|
18174
|
+
};
|
|
18175
|
+
const createFlagExpr = (negate = false) => {
|
|
18176
|
+
const body = unwrapTestExpr();
|
|
18177
|
+
const bodyExpr = negate ? t2.unaryExpression("!", body) : body;
|
|
18178
|
+
return t2.arrowFunctionExpression([], bodyExpr);
|
|
18179
|
+
};
|
|
18180
|
+
if (conseqReactiveOnly || altReactiveOnly) {
|
|
18181
|
+
const stmts = [];
|
|
18182
|
+
const runInScopeId = t2.identifier(RUNTIME_ALIASES.runInScope);
|
|
18183
|
+
const addScoped = (flagExpr, body) => {
|
|
18184
|
+
ctx.helpersUsed.add("runInScope");
|
|
18185
|
+
stmts.push(
|
|
18186
|
+
t2.expressionStatement(
|
|
18187
|
+
t2.callExpression(runInScopeId, [
|
|
18188
|
+
flagExpr,
|
|
18189
|
+
t2.arrowFunctionExpression([], t2.blockStatement(body))
|
|
18190
|
+
])
|
|
18191
|
+
)
|
|
18192
|
+
);
|
|
18193
|
+
};
|
|
18194
|
+
if (conseqReactiveOnly) {
|
|
18195
|
+
addScoped(createFlagExpr(false), conseqStmts);
|
|
18196
|
+
}
|
|
18197
|
+
if (altReactiveOnly && altStmts) {
|
|
18198
|
+
addScoped(createFlagExpr(true), altStmts);
|
|
18199
|
+
}
|
|
18200
|
+
const needsFallbackConseq = !conseqReactiveOnly && conseqStmts.length > 0;
|
|
18201
|
+
const needsFallbackAlt = !altReactiveOnly && altStmts && altStmts.length > 0;
|
|
18202
|
+
if (needsFallbackConseq || needsFallbackAlt) {
|
|
18203
|
+
stmts.push(
|
|
18204
|
+
t2.ifStatement(
|
|
18205
|
+
unwrapTestExpr(),
|
|
18206
|
+
needsFallbackConseq ? t2.blockStatement(conseqStmts) : t2.blockStatement([]),
|
|
18207
|
+
needsFallbackAlt && altStmts ? t2.blockStatement(altStmts) : null
|
|
18208
|
+
)
|
|
18209
|
+
);
|
|
18210
|
+
}
|
|
18211
|
+
return stmts;
|
|
18212
|
+
}
|
|
18213
|
+
const ifStmt = t2.ifStatement(
|
|
18214
|
+
testExpr,
|
|
18215
|
+
t2.blockStatement(conseqStmts),
|
|
18216
|
+
altStmts ? t2.blockStatement(altStmts) : null
|
|
18217
|
+
);
|
|
18056
18218
|
const shouldWrapEffect = ctx.wrapTrackedExpressions !== false && !ctx.inRegionMemo && expressionUsesTracked(node.test, ctx) && !statementHasEarlyExit(ifStmt, t2);
|
|
18057
18219
|
if (shouldWrapEffect) {
|
|
18058
18220
|
ctx.helpersUsed.add("useEffect");
|
|
@@ -19046,6 +19208,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19046
19208
|
if (instr.kind === "Assign") {
|
|
19047
19209
|
const ssaName = instr.target.name;
|
|
19048
19210
|
const baseName2 = deSSAVarName(ssaName);
|
|
19211
|
+
const declKindRaw = instr.declarationKind;
|
|
19049
19212
|
propagateHookResultAlias(baseName2, instr.value, ctx);
|
|
19050
19213
|
const hookMember = resolveHookMemberValue(instr.value, ctx);
|
|
19051
19214
|
if (hookMember) {
|
|
@@ -19055,9 +19218,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19055
19218
|
} else if (hookMember.kind === "memo") {
|
|
19056
19219
|
ctx.memoVars?.add(baseName2);
|
|
19057
19220
|
}
|
|
19058
|
-
|
|
19221
|
+
const declKind2 = declKindRaw && declKindRaw !== "function" ? declKindRaw : null;
|
|
19222
|
+
if (declKind2) {
|
|
19059
19223
|
declaredVars.add(baseName2);
|
|
19060
|
-
return t2.variableDeclaration(
|
|
19224
|
+
return t2.variableDeclaration(declKind2, [
|
|
19061
19225
|
t2.variableDeclarator(t2.identifier(baseName2), hookMember.member)
|
|
19062
19226
|
]);
|
|
19063
19227
|
}
|
|
@@ -19070,11 +19234,25 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19070
19234
|
t2.assignmentExpression("=", t2.identifier(baseName2), hookMember.member)
|
|
19071
19235
|
);
|
|
19072
19236
|
}
|
|
19073
|
-
const declKind =
|
|
19237
|
+
const declKind = declKindRaw && declKindRaw !== "function" ? declKindRaw : void 0;
|
|
19238
|
+
const isFunctionDecl = instr.value.kind === "FunctionExpression" && (declKindRaw === "function" || !declKindRaw && instr.value.name === baseName2);
|
|
19239
|
+
if (isFunctionDecl) {
|
|
19240
|
+
const loweredFn = lowerExpressionWithDeSSA(instr.value, ctx);
|
|
19241
|
+
if (t2.isFunctionExpression(loweredFn)) {
|
|
19242
|
+
declaredVars.add(baseName2);
|
|
19243
|
+
return t2.functionDeclaration(
|
|
19244
|
+
t2.identifier(baseName2),
|
|
19245
|
+
loweredFn.params,
|
|
19246
|
+
loweredFn.body,
|
|
19247
|
+
loweredFn.generator ?? false,
|
|
19248
|
+
loweredFn.async ?? false
|
|
19249
|
+
);
|
|
19250
|
+
}
|
|
19251
|
+
}
|
|
19074
19252
|
const isTracked = ctx.trackedVars.has(baseName2);
|
|
19075
19253
|
const isSignal = ctx.signalVars?.has(baseName2) ?? false;
|
|
19076
19254
|
const aliasVars = ctx.aliasVars ?? (ctx.aliasVars = /* @__PURE__ */ new Set());
|
|
19077
|
-
const dependsOnTracked2 = expressionUsesTracked(instr.value, ctx);
|
|
19255
|
+
const dependsOnTracked2 = expressionUsesTracked(instr.value, ctx) || (ctx.memoVars?.has(baseName2) ?? false);
|
|
19078
19256
|
const capturedTracked = ctx.externalTracked && ctx.externalTracked.has(baseName2) && !declaredVars.has(baseName2);
|
|
19079
19257
|
const isShadowDeclaration = !!declKind && declaredVars.has(baseName2);
|
|
19080
19258
|
const treatAsTracked = !isShadowDeclaration && isTracked;
|
|
@@ -19082,6 +19260,9 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19082
19260
|
const isStateCall2 = instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && instr.value.callee.name === "$state";
|
|
19083
19261
|
const inRegionMemo = ctx.inRegionMemo ?? false;
|
|
19084
19262
|
const isFunctionValue = instr.value.kind === "ArrowFunction" || instr.value.kind === "FunctionExpression";
|
|
19263
|
+
const isAccessorReturningCall = instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && ["$memo", "createMemo", "useProp"].includes(instr.value.callee.name);
|
|
19264
|
+
const isReactiveObjectCall = instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && ["mergeProps", "prop"].includes(instr.value.callee.name);
|
|
19265
|
+
const isMemoReturningCall = isAccessorReturningCall || isReactiveObjectCall;
|
|
19085
19266
|
const lowerAssignedValue = (forceAssigned = false) => lowerExpressionWithDeSSA(instr.value, ctx, forceAssigned || isFunctionValue);
|
|
19086
19267
|
const buildMemoCall = (expr) => {
|
|
19087
19268
|
const args = [
|
|
@@ -19128,7 +19309,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19128
19309
|
t2.variableDeclarator(t2.identifier(baseName2), derivedExpr)
|
|
19129
19310
|
]);
|
|
19130
19311
|
}
|
|
19131
|
-
ctx.memoVars?.add(baseName2);
|
|
19312
|
+
if (!isReactiveObjectCall) ctx.memoVars?.add(baseName2);
|
|
19132
19313
|
if (ctx.noMemo) {
|
|
19133
19314
|
return t2.variableDeclaration(normalizedDecl, [
|
|
19134
19315
|
t2.variableDeclarator(
|
|
@@ -19138,7 +19319,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19138
19319
|
]);
|
|
19139
19320
|
}
|
|
19140
19321
|
return t2.variableDeclaration(normalizedDecl, [
|
|
19141
|
-
t2.variableDeclarator(
|
|
19322
|
+
t2.variableDeclarator(
|
|
19323
|
+
t2.identifier(baseName2),
|
|
19324
|
+
isMemoReturningCall ? derivedExpr : buildMemoCall(derivedExpr)
|
|
19325
|
+
)
|
|
19142
19326
|
]);
|
|
19143
19327
|
}
|
|
19144
19328
|
}
|
|
@@ -19149,7 +19333,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19149
19333
|
t2.variableDeclarator(t2.identifier(baseName2), derivedExpr)
|
|
19150
19334
|
]);
|
|
19151
19335
|
}
|
|
19152
|
-
ctx.memoVars?.add(baseName2);
|
|
19336
|
+
if (!isReactiveObjectCall) ctx.memoVars?.add(baseName2);
|
|
19153
19337
|
if (ctx.noMemo) {
|
|
19154
19338
|
return t2.variableDeclaration(normalizedDecl, [
|
|
19155
19339
|
t2.variableDeclarator(
|
|
@@ -19159,7 +19343,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19159
19343
|
]);
|
|
19160
19344
|
}
|
|
19161
19345
|
return t2.variableDeclaration(normalizedDecl, [
|
|
19162
|
-
t2.variableDeclarator(
|
|
19346
|
+
t2.variableDeclarator(
|
|
19347
|
+
t2.identifier(baseName2),
|
|
19348
|
+
isMemoReturningCall ? derivedExpr : buildMemoCall(derivedExpr)
|
|
19349
|
+
)
|
|
19163
19350
|
]);
|
|
19164
19351
|
}
|
|
19165
19352
|
return t2.variableDeclaration(fallbackDecl, [
|
|
@@ -19217,7 +19404,7 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19217
19404
|
t2.variableDeclarator(t2.identifier(baseName2), derivedExpr)
|
|
19218
19405
|
]);
|
|
19219
19406
|
}
|
|
19220
|
-
ctx.memoVars?.add(baseName2);
|
|
19407
|
+
if (!isReactiveObjectCall) ctx.memoVars?.add(baseName2);
|
|
19221
19408
|
if (ctx.noMemo) {
|
|
19222
19409
|
return t2.variableDeclaration("const", [
|
|
19223
19410
|
t2.variableDeclarator(
|
|
@@ -19227,7 +19414,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19227
19414
|
]);
|
|
19228
19415
|
}
|
|
19229
19416
|
return t2.variableDeclaration("const", [
|
|
19230
|
-
t2.variableDeclarator(
|
|
19417
|
+
t2.variableDeclarator(
|
|
19418
|
+
t2.identifier(baseName2),
|
|
19419
|
+
isMemoReturningCall ? derivedExpr : buildMemoCall(derivedExpr)
|
|
19420
|
+
)
|
|
19231
19421
|
]);
|
|
19232
19422
|
}
|
|
19233
19423
|
return t2.variableDeclaration("let", [
|
|
@@ -19241,22 +19431,17 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19241
19431
|
t2.variableDeclarator(t2.identifier(baseName2), derivedExpr)
|
|
19242
19432
|
]);
|
|
19243
19433
|
}
|
|
19244
|
-
if (ctx.memoVars?.
|
|
19245
|
-
if (buildMemoCall) {
|
|
19246
|
-
console.log("Declaring memo var:", baseName2);
|
|
19247
|
-
return t2.variableDeclaration("const", [
|
|
19248
|
-
t2.variableDeclarator(t2.identifier(baseName2), buildMemoCall(derivedExpr))
|
|
19249
|
-
]);
|
|
19250
|
-
}
|
|
19251
|
-
}
|
|
19252
|
-
ctx.memoVars?.add(baseName2);
|
|
19434
|
+
if (!isReactiveObjectCall) ctx.memoVars?.add(baseName2);
|
|
19253
19435
|
if (ctx.noMemo) {
|
|
19254
19436
|
return t2.variableDeclaration("const", [
|
|
19255
19437
|
t2.variableDeclarator(t2.identifier(baseName2), t2.arrowFunctionExpression([], derivedExpr))
|
|
19256
19438
|
]);
|
|
19257
19439
|
}
|
|
19258
19440
|
return t2.variableDeclaration("const", [
|
|
19259
|
-
t2.variableDeclarator(
|
|
19441
|
+
t2.variableDeclarator(
|
|
19442
|
+
t2.identifier(baseName2),
|
|
19443
|
+
isMemoReturningCall ? derivedExpr : buildMemoCall(derivedExpr)
|
|
19444
|
+
)
|
|
19260
19445
|
]);
|
|
19261
19446
|
}
|
|
19262
19447
|
return t2.variableDeclaration("let", [
|
|
@@ -20334,7 +20519,8 @@ function collectExpressionIdentifiersDeep(expr, into, bound = /* @__PURE__ */ ne
|
|
|
20334
20519
|
case "CallExpression":
|
|
20335
20520
|
case "OptionalCallExpression": {
|
|
20336
20521
|
const isMacroCallee = expr.callee.kind === "Identifier" && (expr.callee.name === "$state" || expr.callee.name === "$effect" || expr.callee.name === "$store");
|
|
20337
|
-
|
|
20522
|
+
const isIIFE = expr.callee.kind === "ArrowFunction" || expr.callee.kind === "FunctionExpression";
|
|
20523
|
+
if (!isMacroCallee && !isIIFE) {
|
|
20338
20524
|
collectExpressionIdentifiersDeep(expr.callee, into, bound);
|
|
20339
20525
|
}
|
|
20340
20526
|
expr.arguments.forEach(
|
|
@@ -20375,73 +20561,81 @@ function collectExpressionIdentifiersDeep(expr, into, bound = /* @__PURE__ */ ne
|
|
|
20375
20561
|
);
|
|
20376
20562
|
return;
|
|
20377
20563
|
case "ArrowFunction": {
|
|
20378
|
-
const
|
|
20379
|
-
expr.params.forEach((p) => nextBound.add(deSSAVarName(p.name)));
|
|
20564
|
+
const tempSet = /* @__PURE__ */ new Set();
|
|
20380
20565
|
if (expr.isExpression && expr.body && !Array.isArray(expr.body)) {
|
|
20381
|
-
|
|
20566
|
+
collectExpressionIdentifiers(expr.body, tempSet);
|
|
20382
20567
|
} else if (Array.isArray(expr.body)) {
|
|
20383
20568
|
for (const block of expr.body) {
|
|
20384
20569
|
for (const instr of block.instructions) {
|
|
20385
20570
|
if (instr.kind === "Assign") {
|
|
20386
|
-
|
|
20571
|
+
collectExpressionIdentifiers(instr.value, tempSet);
|
|
20387
20572
|
} else if (instr.kind === "Expression") {
|
|
20388
|
-
|
|
20573
|
+
collectExpressionIdentifiers(instr.value, tempSet);
|
|
20389
20574
|
} else if (instr.kind === "Phi") {
|
|
20390
|
-
instr.sources.forEach((src) =>
|
|
20575
|
+
instr.sources.forEach((src) => tempSet.add(deSSAVarName(src.id.name)));
|
|
20391
20576
|
}
|
|
20392
20577
|
}
|
|
20393
20578
|
const term = block.terminator;
|
|
20394
20579
|
if (term.kind === "Branch") {
|
|
20395
|
-
|
|
20580
|
+
collectExpressionIdentifiers(term.test, tempSet);
|
|
20396
20581
|
} else if (term.kind === "Switch") {
|
|
20397
|
-
|
|
20582
|
+
collectExpressionIdentifiers(term.discriminant, tempSet);
|
|
20398
20583
|
term.cases.forEach((c) => {
|
|
20399
|
-
if (c.test)
|
|
20584
|
+
if (c.test) collectExpressionIdentifiers(c.test, tempSet);
|
|
20400
20585
|
});
|
|
20401
20586
|
} else if (term.kind === "ForOf") {
|
|
20402
|
-
|
|
20587
|
+
collectExpressionIdentifiers(term.iterable, tempSet);
|
|
20403
20588
|
} else if (term.kind === "ForIn") {
|
|
20404
|
-
|
|
20589
|
+
collectExpressionIdentifiers(term.object, tempSet);
|
|
20405
20590
|
} else if (term.kind === "Return" && term.argument) {
|
|
20406
|
-
|
|
20591
|
+
collectExpressionIdentifiers(term.argument, tempSet);
|
|
20407
20592
|
} else if (term.kind === "Throw") {
|
|
20408
|
-
|
|
20593
|
+
collectExpressionIdentifiers(term.argument, tempSet);
|
|
20409
20594
|
}
|
|
20410
20595
|
}
|
|
20411
20596
|
}
|
|
20597
|
+
const paramNames = new Set(expr.params.map((p) => deSSAVarName(p.name)));
|
|
20598
|
+
for (const name of bound) paramNames.add(name);
|
|
20599
|
+
for (const dep of tempSet) {
|
|
20600
|
+
if (!paramNames.has(dep)) into.add(dep);
|
|
20601
|
+
}
|
|
20412
20602
|
return;
|
|
20413
20603
|
}
|
|
20414
20604
|
case "FunctionExpression": {
|
|
20415
|
-
const
|
|
20416
|
-
expr.params.forEach((p) => nextBound.add(deSSAVarName(p.name)));
|
|
20605
|
+
const tempSet = /* @__PURE__ */ new Set();
|
|
20417
20606
|
for (const block of expr.body) {
|
|
20418
20607
|
for (const instr of block.instructions) {
|
|
20419
20608
|
if (instr.kind === "Assign") {
|
|
20420
|
-
|
|
20609
|
+
collectExpressionIdentifiers(instr.value, tempSet);
|
|
20421
20610
|
} else if (instr.kind === "Expression") {
|
|
20422
|
-
|
|
20611
|
+
collectExpressionIdentifiers(instr.value, tempSet);
|
|
20423
20612
|
} else if (instr.kind === "Phi") {
|
|
20424
|
-
instr.sources.forEach((src) =>
|
|
20613
|
+
instr.sources.forEach((src) => tempSet.add(deSSAVarName(src.id.name)));
|
|
20425
20614
|
}
|
|
20426
20615
|
}
|
|
20427
20616
|
const term = block.terminator;
|
|
20428
20617
|
if (term.kind === "Branch") {
|
|
20429
|
-
|
|
20618
|
+
collectExpressionIdentifiers(term.test, tempSet);
|
|
20430
20619
|
} else if (term.kind === "Switch") {
|
|
20431
|
-
|
|
20620
|
+
collectExpressionIdentifiers(term.discriminant, tempSet);
|
|
20432
20621
|
term.cases.forEach((c) => {
|
|
20433
|
-
if (c.test)
|
|
20622
|
+
if (c.test) collectExpressionIdentifiers(c.test, tempSet);
|
|
20434
20623
|
});
|
|
20435
20624
|
} else if (term.kind === "ForOf") {
|
|
20436
|
-
|
|
20625
|
+
collectExpressionIdentifiers(term.iterable, tempSet);
|
|
20437
20626
|
} else if (term.kind === "ForIn") {
|
|
20438
|
-
|
|
20627
|
+
collectExpressionIdentifiers(term.object, tempSet);
|
|
20439
20628
|
} else if (term.kind === "Return" && term.argument) {
|
|
20440
|
-
|
|
20629
|
+
collectExpressionIdentifiers(term.argument, tempSet);
|
|
20441
20630
|
} else if (term.kind === "Throw") {
|
|
20442
|
-
|
|
20631
|
+
collectExpressionIdentifiers(term.argument, tempSet);
|
|
20443
20632
|
}
|
|
20444
20633
|
}
|
|
20634
|
+
const paramNames = new Set(expr.params.map((p) => deSSAVarName(p.name)));
|
|
20635
|
+
for (const name of bound) paramNames.add(name);
|
|
20636
|
+
for (const dep of tempSet) {
|
|
20637
|
+
if (!paramNames.has(dep)) into.add(dep);
|
|
20638
|
+
}
|
|
20445
20639
|
return;
|
|
20446
20640
|
}
|
|
20447
20641
|
case "AssignmentExpression":
|
|
@@ -20510,6 +20704,13 @@ function getExpressionIdentifiers(expr) {
|
|
|
20510
20704
|
}
|
|
20511
20705
|
return deps;
|
|
20512
20706
|
}
|
|
20707
|
+
function getExpressionIdentifiersDeep(expr) {
|
|
20708
|
+
const deps = /* @__PURE__ */ new Set();
|
|
20709
|
+
if (expr) {
|
|
20710
|
+
collectExpressionIdentifiersDeep(expr, deps);
|
|
20711
|
+
}
|
|
20712
|
+
return deps;
|
|
20713
|
+
}
|
|
20513
20714
|
function buildControlDependencyMap(fn) {
|
|
20514
20715
|
const depsByInstruction = /* @__PURE__ */ new Map();
|
|
20515
20716
|
let structured;
|
|
@@ -20636,7 +20837,7 @@ function computeReactiveAccessors(fn, ctx) {
|
|
|
20636
20837
|
for (const instr of block.instructions) {
|
|
20637
20838
|
if (instr.kind === "Assign") {
|
|
20638
20839
|
const target = deSSAVarName(instr.target.name);
|
|
20639
|
-
const dataDeps =
|
|
20840
|
+
const dataDeps = getExpressionIdentifiersDeep(instr.value);
|
|
20640
20841
|
addDepsToTarget(target, dataDeps, dataDepsByTarget);
|
|
20641
20842
|
const controlDeps = controlDepsByInstr.get(instr) ?? /* @__PURE__ */ new Set();
|
|
20642
20843
|
addDepsToTarget(target, controlDeps, controlDepsByTarget);
|
|
@@ -20697,7 +20898,7 @@ function computeReactiveAccessors(fn, ctx) {
|
|
|
20697
20898
|
if (instr.kind === "Assign") {
|
|
20698
20899
|
const target = deSSAVarName(instr.target.name);
|
|
20699
20900
|
if (isFunctionVar(target)) continue;
|
|
20700
|
-
const dataDeps =
|
|
20901
|
+
const dataDeps = getExpressionIdentifiersDeep(instr.value);
|
|
20701
20902
|
const controlDepsForInstr = controlDepsByInstr.get(instr) ?? /* @__PURE__ */ new Set();
|
|
20702
20903
|
const hasDataDep = Array.from(dataDeps).some((dep) => tracked.has(dep));
|
|
20703
20904
|
const hasControlDep = Array.from(controlDepsForInstr).some((dep) => tracked.has(dep));
|
|
@@ -20707,7 +20908,8 @@ function computeReactiveAccessors(fn, ctx) {
|
|
|
20707
20908
|
tracked.add(target);
|
|
20708
20909
|
changed = true;
|
|
20709
20910
|
}
|
|
20710
|
-
|
|
20911
|
+
const isReactiveObjectCall = instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && ["mergeProps", "prop"].includes(instr.value.callee.name);
|
|
20912
|
+
if (hasDataDep && !isSignal(target) && !isStore(target) && !isReactiveObjectCall) {
|
|
20711
20913
|
memo.add(target);
|
|
20712
20914
|
}
|
|
20713
20915
|
} else if (instr.kind === "Phi") {
|
|
@@ -20795,6 +20997,20 @@ function lowerInstruction(instr, ctx) {
|
|
|
20795
20997
|
const { t: t2 } = ctx;
|
|
20796
20998
|
if (instr.kind === "Assign") {
|
|
20797
20999
|
const baseName2 = deSSAVarName(instr.target.name);
|
|
21000
|
+
const isFunctionDecl = instr.value.kind === "FunctionExpression" && (instr.declarationKind === "function" || !instr.declarationKind && instr.value.name === baseName2);
|
|
21001
|
+
if (isFunctionDecl) {
|
|
21002
|
+
const loweredFn = lowerExpression(instr.value, ctx);
|
|
21003
|
+
if (t2.isFunctionExpression(loweredFn)) {
|
|
21004
|
+
return t2.functionDeclaration(
|
|
21005
|
+
t2.identifier(baseName2),
|
|
21006
|
+
loweredFn.params,
|
|
21007
|
+
loweredFn.body,
|
|
21008
|
+
loweredFn.generator ?? false,
|
|
21009
|
+
loweredFn.async ?? false
|
|
21010
|
+
);
|
|
21011
|
+
}
|
|
21012
|
+
}
|
|
21013
|
+
const declKind = instr.declarationKind === "function" ? void 0 : instr.declarationKind;
|
|
20798
21014
|
propagateHookResultAlias(baseName2, instr.value, ctx);
|
|
20799
21015
|
const hookMember = resolveHookMemberValue(instr.value, ctx);
|
|
20800
21016
|
if (hookMember) {
|
|
@@ -20804,8 +21020,8 @@ function lowerInstruction(instr, ctx) {
|
|
|
20804
21020
|
} else if (hookMember.kind === "memo") {
|
|
20805
21021
|
ctx.memoVars?.add(baseName2);
|
|
20806
21022
|
}
|
|
20807
|
-
if (
|
|
20808
|
-
return t2.variableDeclaration(
|
|
21023
|
+
if (declKind) {
|
|
21024
|
+
return t2.variableDeclaration(declKind, [
|
|
20809
21025
|
t2.variableDeclarator(t2.identifier(baseName2), hookMember.member)
|
|
20810
21026
|
]);
|
|
20811
21027
|
}
|
|
@@ -21204,6 +21420,13 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21204
21420
|
return t2.callExpression(t2.identifier(RUNTIME_ALIASES.mergeProps), args);
|
|
21205
21421
|
}
|
|
21206
21422
|
const isIIFE = (expr.callee.kind === "ArrowFunction" || expr.callee.kind === "FunctionExpression") && expr.arguments.length === 0 && expr.callee.params.length === 0;
|
|
21423
|
+
const calleeName = expr.callee.kind === "Identifier" ? deSSAVarName(expr.callee.name) : null;
|
|
21424
|
+
const calleeIsMemoAccessor = !!calleeName && ctx.memoVars?.has(calleeName);
|
|
21425
|
+
const calleeIsSignalLike = !!calleeName && (ctx.signalVars?.has(calleeName) || ctx.storeVars?.has(calleeName));
|
|
21426
|
+
if (calleeIsMemoAccessor && !calleeIsSignalLike && expr.arguments.length > 0) {
|
|
21427
|
+
const loweredArgs = expr.arguments.map((a) => lowerExpression(a, ctx));
|
|
21428
|
+
return t2.callExpression(t2.callExpression(t2.identifier(calleeName), []), loweredArgs);
|
|
21429
|
+
}
|
|
21207
21430
|
const lowerCallee = () => isIIFE ? withNonReactiveScope(ctx, () => lowerExpression(expr.callee, ctx)) : lowerExpression(expr.callee, ctx);
|
|
21208
21431
|
return t2.callExpression(
|
|
21209
21432
|
lowerCallee(),
|
|
@@ -21556,11 +21779,12 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21556
21779
|
return t2.identifier("undefined");
|
|
21557
21780
|
}
|
|
21558
21781
|
}
|
|
21559
|
-
function lowerDomExpression(expr, ctx, region) {
|
|
21782
|
+
function lowerDomExpression(expr, ctx, region, options) {
|
|
21560
21783
|
let lowered = lowerExpression(expr, ctx);
|
|
21561
|
-
|
|
21784
|
+
const skipHookAccessors = options?.skipHookAccessors ?? false;
|
|
21785
|
+
if (!skipHookAccessors && ctx.t.isMemberExpression(lowered) && ctx.t.isIdentifier(lowered.object) && ctx.hookResultVarMap?.has(deSSAVarName(lowered.object.name))) {
|
|
21562
21786
|
lowered = ctx.t.callExpression(lowered, []);
|
|
21563
|
-
} else if (ctx.t.isIdentifier(lowered)) {
|
|
21787
|
+
} else if (!skipHookAccessors && ctx.t.isIdentifier(lowered)) {
|
|
21564
21788
|
const hookName = ctx.hookResultVarMap?.get(deSSAVarName(lowered.name));
|
|
21565
21789
|
if (hookName) {
|
|
21566
21790
|
const info = getHookReturnInfo(hookName, ctx);
|
|
@@ -21569,7 +21793,9 @@ function lowerDomExpression(expr, ctx, region) {
|
|
|
21569
21793
|
}
|
|
21570
21794
|
}
|
|
21571
21795
|
}
|
|
21572
|
-
return applyRegionMetadataToExpression(lowered, ctx, region
|
|
21796
|
+
return applyRegionMetadataToExpression(lowered, ctx, region, {
|
|
21797
|
+
skipRootOverride: options?.skipRegionRootOverride
|
|
21798
|
+
});
|
|
21573
21799
|
}
|
|
21574
21800
|
function lowerJSXChildNonFineGrained(child, ctx) {
|
|
21575
21801
|
const { t: t2 } = ctx;
|
|
@@ -21778,12 +22004,13 @@ function getDependencyPathFromNode(node, t2) {
|
|
|
21778
22004
|
}
|
|
21779
22005
|
return null;
|
|
21780
22006
|
}
|
|
21781
|
-
function applyRegionMetadataToExpression(expr, ctx, regionOverride) {
|
|
22007
|
+
function applyRegionMetadataToExpression(expr, ctx, regionOverride, options) {
|
|
21782
22008
|
if (ctx.inReturn && ctx.currentFnIsHook) {
|
|
21783
22009
|
return expr;
|
|
21784
22010
|
}
|
|
21785
22011
|
const region = regionOverride ?? ctx.currentRegion;
|
|
21786
22012
|
if (!region) return expr;
|
|
22013
|
+
const skipRootOverride = options?.skipRootOverride ?? false;
|
|
21787
22014
|
const metadata = regionInfoToMetadata(region);
|
|
21788
22015
|
const state = {};
|
|
21789
22016
|
applyRegionMetadata(state, {
|
|
@@ -21836,7 +22063,7 @@ function applyRegionMetadataToExpression(expr, ctx, regionOverride) {
|
|
|
21836
22063
|
if (Object.keys(overrides).length === 0) {
|
|
21837
22064
|
return expr;
|
|
21838
22065
|
}
|
|
21839
|
-
if (ctx.t.isIdentifier(expr)) {
|
|
22066
|
+
if (!skipRootOverride && ctx.t.isIdentifier(expr)) {
|
|
21840
22067
|
const key = normalizeDependencyKey2(expr.name);
|
|
21841
22068
|
const direct = overrides[key] ?? overrides[expr.name];
|
|
21842
22069
|
if (direct) {
|
|
@@ -21844,10 +22071,10 @@ function applyRegionMetadataToExpression(expr, ctx, regionOverride) {
|
|
|
21844
22071
|
}
|
|
21845
22072
|
}
|
|
21846
22073
|
const cloned = ctx.t.cloneNode(expr, true);
|
|
21847
|
-
replaceIdentifiersWithOverrides(cloned, overrides, ctx.t);
|
|
22074
|
+
replaceIdentifiersWithOverrides(cloned, overrides, ctx.t, void 0, void 0, skipRootOverride);
|
|
21848
22075
|
return cloned;
|
|
21849
22076
|
}
|
|
21850
|
-
function replaceIdentifiersWithOverrides(node, overrides, t2, parentKind, parentKey) {
|
|
22077
|
+
function replaceIdentifiersWithOverrides(node, overrides, t2, parentKind, parentKey, skipCurrentNode = false) {
|
|
21851
22078
|
const isCallTarget = parentKey === "callee" && (parentKind === "CallExpression" || parentKind === "OptionalCallExpression");
|
|
21852
22079
|
const collectParamNames = (params) => {
|
|
21853
22080
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -21883,7 +22110,7 @@ function replaceIdentifiersWithOverrides(node, overrides, t2, parentKind, parent
|
|
|
21883
22110
|
params.forEach((p) => visitPattern(p));
|
|
21884
22111
|
return names;
|
|
21885
22112
|
};
|
|
21886
|
-
if (t2.isMemberExpression(node) || t2.isOptionalMemberExpression(node)) {
|
|
22113
|
+
if (!skipCurrentNode && (t2.isMemberExpression(node) || t2.isOptionalMemberExpression(node))) {
|
|
21887
22114
|
const path = getDependencyPathFromNode(node, t2);
|
|
21888
22115
|
const normalized = path ? normalizeDependencyKey2(path) : null;
|
|
21889
22116
|
const override = normalized && overrides[normalized] || (path ? overrides[path] : void 0);
|
|
@@ -21893,7 +22120,7 @@ function replaceIdentifiersWithOverrides(node, overrides, t2, parentKind, parent
|
|
|
21893
22120
|
return;
|
|
21894
22121
|
}
|
|
21895
22122
|
}
|
|
21896
|
-
if (t2.isIdentifier(node)) {
|
|
22123
|
+
if (!skipCurrentNode && t2.isIdentifier(node)) {
|
|
21897
22124
|
const key = normalizeDependencyKey2(node.name);
|
|
21898
22125
|
const override = overrides[key] ?? overrides[node.name];
|
|
21899
22126
|
if (override && !isCallTarget) {
|
|
@@ -21938,7 +22165,8 @@ function replaceIdentifiersWithOverrides(node, overrides, t2, parentKind, parent
|
|
|
21938
22165
|
overrides,
|
|
21939
22166
|
t2,
|
|
21940
22167
|
node.type,
|
|
21941
|
-
key
|
|
22168
|
+
key,
|
|
22169
|
+
false
|
|
21942
22170
|
);
|
|
21943
22171
|
}
|
|
21944
22172
|
}
|
|
@@ -22367,7 +22595,10 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
22367
22595
|
const shouldWrapHandler = isExpressionReactive(binding.expr, ctx);
|
|
22368
22596
|
const prevWrapTracked = ctx.wrapTrackedExpressions;
|
|
22369
22597
|
ctx.wrapTrackedExpressions = false;
|
|
22370
|
-
const valueExpr = lowerDomExpression(binding.expr, ctx, containingRegion
|
|
22598
|
+
const valueExpr = lowerDomExpression(binding.expr, ctx, containingRegion, {
|
|
22599
|
+
skipHookAccessors: true,
|
|
22600
|
+
skipRegionRootOverride: true
|
|
22601
|
+
});
|
|
22371
22602
|
ctx.wrapTrackedExpressions = prevWrapTracked;
|
|
22372
22603
|
const eventParam = t2.identifier("_e");
|
|
22373
22604
|
const isFn = t2.isArrowFunctionExpression(valueExpr) || t2.isFunctionExpression(valueExpr);
|
|
@@ -24093,6 +24324,9 @@ function isInsideNestedFunction(path) {
|
|
|
24093
24324
|
}
|
|
24094
24325
|
return false;
|
|
24095
24326
|
}
|
|
24327
|
+
function isInsideJSX(path) {
|
|
24328
|
+
return !!path.findParent((p) => p.isJSXElement?.() || p.isJSXFragment?.());
|
|
24329
|
+
}
|
|
24096
24330
|
function emitWarning(node, code, message, options, fileName) {
|
|
24097
24331
|
if (!options.onWarn) return;
|
|
24098
24332
|
const loc = node.loc?.start;
|
|
@@ -24190,6 +24424,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24190
24424
|
const root = getRootIdentifier(expr, t2);
|
|
24191
24425
|
return !!(root && stateVars.has(root.name));
|
|
24192
24426
|
};
|
|
24427
|
+
const reactiveNames = /* @__PURE__ */ new Set([...stateVars, ...derivedVars]);
|
|
24193
24428
|
programPath.traverse({
|
|
24194
24429
|
AssignmentExpression(path) {
|
|
24195
24430
|
const { left } = path.node;
|
|
@@ -24252,6 +24487,35 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24252
24487
|
);
|
|
24253
24488
|
}
|
|
24254
24489
|
},
|
|
24490
|
+
Function(path) {
|
|
24491
|
+
const captured = /* @__PURE__ */ new Set();
|
|
24492
|
+
path.traverse(
|
|
24493
|
+
{
|
|
24494
|
+
Function(inner) {
|
|
24495
|
+
if (inner === path) return;
|
|
24496
|
+
inner.skip();
|
|
24497
|
+
},
|
|
24498
|
+
Identifier(idPath) {
|
|
24499
|
+
const name = idPath.node.name;
|
|
24500
|
+
if (!reactiveNames.has(name)) return;
|
|
24501
|
+
const binding = idPath.scope.getBinding(name);
|
|
24502
|
+
if (!binding) return;
|
|
24503
|
+
if (binding.scope === idPath.scope || binding.scope === path.scope) return;
|
|
24504
|
+
captured.add(name);
|
|
24505
|
+
}
|
|
24506
|
+
},
|
|
24507
|
+
{}
|
|
24508
|
+
);
|
|
24509
|
+
if (captured.size > 0) {
|
|
24510
|
+
emitWarning(
|
|
24511
|
+
path.node,
|
|
24512
|
+
"FICT-R005",
|
|
24513
|
+
`Function captures reactive variable(s): ${Array.from(captured).join(", ")}. Pass them as parameters or memoize explicitly to avoid hidden dependencies.`,
|
|
24514
|
+
options,
|
|
24515
|
+
fileName
|
|
24516
|
+
);
|
|
24517
|
+
}
|
|
24518
|
+
},
|
|
24255
24519
|
CallExpression(path) {
|
|
24256
24520
|
if (t2.isIdentifier(path.node.callee, { name: "$effect" })) {
|
|
24257
24521
|
const argPath = path.get("arguments.0");
|
|
@@ -24573,6 +24837,15 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24573
24837
|
}
|
|
24574
24838
|
const callee = callPath.node.callee;
|
|
24575
24839
|
const calleeId = t2.isIdentifier(callee) ? callee.name : null;
|
|
24840
|
+
if (calleeId && (calleeId === "createEffect" || calleeId === "createMemo" || calleeId === "createSelector") && fictImports.has(calleeId) && (isInsideLoop(callPath) || isInsideConditional(callPath)) && !isInsideJSX(callPath)) {
|
|
24841
|
+
emitWarning(
|
|
24842
|
+
callPath.node,
|
|
24843
|
+
"FICT-R004",
|
|
24844
|
+
"Reactive creation inside non-JSX control flow will not auto-dispose; wrap it in createScope/runInScope or move it into JSX-managed regions.",
|
|
24845
|
+
options,
|
|
24846
|
+
fileName
|
|
24847
|
+
);
|
|
24848
|
+
}
|
|
24576
24849
|
const allowedStateCallees = /* @__PURE__ */ new Set([
|
|
24577
24850
|
"$effect",
|
|
24578
24851
|
"$memo",
|