@fictjs/compiler 0.5.2 → 0.6.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 +1226 -233
- package/dist/index.js +1226 -233
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -101,7 +101,7 @@ var require_generated = __commonJS({
|
|
|
101
101
|
});
|
|
102
102
|
exports.isAccessor = isAccessor;
|
|
103
103
|
exports.isAnyTypeAnnotation = isAnyTypeAnnotation;
|
|
104
|
-
exports.isArgumentPlaceholder =
|
|
104
|
+
exports.isArgumentPlaceholder = isArgumentPlaceholder2;
|
|
105
105
|
exports.isArrayExpression = isArrayExpression2;
|
|
106
106
|
exports.isArrayPattern = isArrayPattern4;
|
|
107
107
|
exports.isArrayTypeAnnotation = isArrayTypeAnnotation;
|
|
@@ -125,7 +125,7 @@ var require_generated = __commonJS({
|
|
|
125
125
|
exports.isClass = isClass;
|
|
126
126
|
exports.isClassAccessorProperty = isClassAccessorProperty;
|
|
127
127
|
exports.isClassBody = isClassBody;
|
|
128
|
-
exports.isClassDeclaration =
|
|
128
|
+
exports.isClassDeclaration = isClassDeclaration3;
|
|
129
129
|
exports.isClassExpression = isClassExpression2;
|
|
130
130
|
exports.isClassImplements = isClassImplements;
|
|
131
131
|
exports.isClassMethod = isClassMethod;
|
|
@@ -155,7 +155,7 @@ var require_generated = __commonJS({
|
|
|
155
155
|
exports.isDirectiveLiteral = isDirectiveLiteral;
|
|
156
156
|
exports.isDoExpression = isDoExpression;
|
|
157
157
|
exports.isDoWhileStatement = isDoWhileStatement2;
|
|
158
|
-
exports.isEmptyStatement =
|
|
158
|
+
exports.isEmptyStatement = isEmptyStatement2;
|
|
159
159
|
exports.isEmptyTypeAnnotation = isEmptyTypeAnnotation;
|
|
160
160
|
exports.isEnumBody = isEnumBody;
|
|
161
161
|
exports.isEnumBooleanBody = isEnumBooleanBody;
|
|
@@ -226,14 +226,14 @@ var require_generated = __commonJS({
|
|
|
226
226
|
exports.isJSXFragment = isJSXFragment2;
|
|
227
227
|
exports.isJSXIdentifier = isJSXIdentifier2;
|
|
228
228
|
exports.isJSXMemberExpression = isJSXMemberExpression2;
|
|
229
|
-
exports.isJSXNamespacedName =
|
|
229
|
+
exports.isJSXNamespacedName = isJSXNamespacedName2;
|
|
230
230
|
exports.isJSXOpeningElement = isJSXOpeningElement;
|
|
231
231
|
exports.isJSXOpeningFragment = isJSXOpeningFragment;
|
|
232
232
|
exports.isJSXSpreadAttribute = isJSXSpreadAttribute2;
|
|
233
|
-
exports.isJSXSpreadChild =
|
|
233
|
+
exports.isJSXSpreadChild = isJSXSpreadChild2;
|
|
234
234
|
exports.isJSXText = isJSXText2;
|
|
235
235
|
exports.isLVal = isLVal;
|
|
236
|
-
exports.isLabeledStatement =
|
|
236
|
+
exports.isLabeledStatement = isLabeledStatement2;
|
|
237
237
|
exports.isLiteral = isLiteral;
|
|
238
238
|
exports.isLogicalExpression = isLogicalExpression2;
|
|
239
239
|
exports.isLoop = isLoop;
|
|
@@ -271,7 +271,7 @@ var require_generated = __commonJS({
|
|
|
271
271
|
exports.isOptionalMemberExpression = isOptionalMemberExpression2;
|
|
272
272
|
exports.isParenthesizedExpression = isParenthesizedExpression2;
|
|
273
273
|
exports.isPattern = isPattern2;
|
|
274
|
-
exports.isPatternLike =
|
|
274
|
+
exports.isPatternLike = isPatternLike3;
|
|
275
275
|
exports.isPipelineBareFunction = isPipelineBareFunction;
|
|
276
276
|
exports.isPipelinePrimaryTopicReference = isPipelinePrimaryTopicReference;
|
|
277
277
|
exports.isPipelineTopicExpression = isPipelineTopicExpression;
|
|
@@ -479,7 +479,7 @@ var require_generated = __commonJS({
|
|
|
479
479
|
if (node.type !== "DoWhileStatement") return false;
|
|
480
480
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
481
481
|
}
|
|
482
|
-
function
|
|
482
|
+
function isEmptyStatement2(node, opts) {
|
|
483
483
|
if (!node) return false;
|
|
484
484
|
if (node.type !== "EmptyStatement") return false;
|
|
485
485
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
@@ -524,7 +524,7 @@ var require_generated = __commonJS({
|
|
|
524
524
|
if (node.type !== "IfStatement") return false;
|
|
525
525
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
526
526
|
}
|
|
527
|
-
function
|
|
527
|
+
function isLabeledStatement2(node, opts) {
|
|
528
528
|
if (!node) return false;
|
|
529
529
|
if (node.type !== "LabeledStatement") return false;
|
|
530
530
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
@@ -689,7 +689,7 @@ var require_generated = __commonJS({
|
|
|
689
689
|
if (node.type !== "ClassExpression") return false;
|
|
690
690
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
691
691
|
}
|
|
692
|
-
function
|
|
692
|
+
function isClassDeclaration3(node, opts) {
|
|
693
693
|
if (!node) return false;
|
|
694
694
|
if (node.type !== "ClassDeclaration") return false;
|
|
695
695
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
@@ -1204,7 +1204,7 @@ var require_generated = __commonJS({
|
|
|
1204
1204
|
if (node.type !== "JSXExpressionContainer") return false;
|
|
1205
1205
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
1206
1206
|
}
|
|
1207
|
-
function
|
|
1207
|
+
function isJSXSpreadChild2(node, opts) {
|
|
1208
1208
|
if (!node) return false;
|
|
1209
1209
|
if (node.type !== "JSXSpreadChild") return false;
|
|
1210
1210
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
@@ -1219,7 +1219,7 @@ var require_generated = __commonJS({
|
|
|
1219
1219
|
if (node.type !== "JSXMemberExpression") return false;
|
|
1220
1220
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
1221
1221
|
}
|
|
1222
|
-
function
|
|
1222
|
+
function isJSXNamespacedName2(node, opts) {
|
|
1223
1223
|
if (!node) return false;
|
|
1224
1224
|
if (node.type !== "JSXNamespacedName") return false;
|
|
1225
1225
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
@@ -1269,7 +1269,7 @@ var require_generated = __commonJS({
|
|
|
1269
1269
|
if (node.type !== "V8IntrinsicIdentifier") return false;
|
|
1270
1270
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
1271
1271
|
}
|
|
1272
|
-
function
|
|
1272
|
+
function isArgumentPlaceholder2(node, opts) {
|
|
1273
1273
|
if (!node) return false;
|
|
1274
1274
|
if (node.type !== "ArgumentPlaceholder") return false;
|
|
1275
1275
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
@@ -2210,7 +2210,7 @@ var require_generated = __commonJS({
|
|
|
2210
2210
|
}
|
|
2211
2211
|
return opts == null || (0, _shallowEqual.default)(node, opts);
|
|
2212
2212
|
}
|
|
2213
|
-
function
|
|
2213
|
+
function isPatternLike3(node, opts) {
|
|
2214
2214
|
if (!node) return false;
|
|
2215
2215
|
switch (node.type) {
|
|
2216
2216
|
case "Identifier":
|
|
@@ -7185,7 +7185,7 @@ var require_lowercase = __commonJS({
|
|
|
7185
7185
|
exports.classAccessorProperty = classAccessorProperty;
|
|
7186
7186
|
exports.classBody = classBody;
|
|
7187
7187
|
exports.classDeclaration = classDeclaration;
|
|
7188
|
-
exports.classExpression =
|
|
7188
|
+
exports.classExpression = classExpression2;
|
|
7189
7189
|
exports.classImplements = classImplements;
|
|
7190
7190
|
exports.classMethod = classMethod;
|
|
7191
7191
|
exports.classPrivateMethod = classPrivateMethod;
|
|
@@ -8047,7 +8047,7 @@ var require_lowercase = __commonJS({
|
|
|
8047
8047
|
validate(defs.body, node, "body", body, 1);
|
|
8048
8048
|
return node;
|
|
8049
8049
|
}
|
|
8050
|
-
function
|
|
8050
|
+
function classExpression2(id = null, superClass = null, body, decorators = null) {
|
|
8051
8051
|
const node = {
|
|
8052
8052
|
type: "ClassExpression",
|
|
8053
8053
|
id,
|
|
@@ -14596,6 +14596,14 @@ function parseFictReturnAnnotation(node) {
|
|
|
14596
14596
|
}
|
|
14597
14597
|
function extractIdentifiersFromPattern(pattern) {
|
|
14598
14598
|
const ids = [];
|
|
14599
|
+
if (t.isRestElement(pattern)) {
|
|
14600
|
+
if (t.isIdentifier(pattern.argument)) {
|
|
14601
|
+
ids.push({ kind: "Identifier", name: pattern.argument.name });
|
|
14602
|
+
} else if (t.isPatternLike(pattern.argument)) {
|
|
14603
|
+
ids.push(...extractIdentifiersFromPattern(pattern.argument));
|
|
14604
|
+
}
|
|
14605
|
+
return ids;
|
|
14606
|
+
}
|
|
14599
14607
|
if (t.isObjectPattern(pattern)) {
|
|
14600
14608
|
for (const prop of pattern.properties) {
|
|
14601
14609
|
if (t.isObjectProperty(prop)) {
|
|
@@ -14604,14 +14612,18 @@ function extractIdentifiersFromPattern(pattern) {
|
|
|
14604
14612
|
} else if (t.isAssignmentPattern(prop.value)) {
|
|
14605
14613
|
if (t.isIdentifier(prop.value.left)) {
|
|
14606
14614
|
ids.push({ kind: "Identifier", name: prop.value.left.name });
|
|
14607
|
-
} else if (t.
|
|
14615
|
+
} else if (t.isPatternLike(prop.value.left)) {
|
|
14608
14616
|
ids.push(...extractIdentifiersFromPattern(prop.value.left));
|
|
14609
14617
|
}
|
|
14610
|
-
} else if (t.
|
|
14618
|
+
} else if (t.isPatternLike(prop.value)) {
|
|
14611
14619
|
ids.push(...extractIdentifiersFromPattern(prop.value));
|
|
14612
14620
|
}
|
|
14613
|
-
} else if (t.isRestElement(prop)
|
|
14614
|
-
|
|
14621
|
+
} else if (t.isRestElement(prop)) {
|
|
14622
|
+
if (t.isIdentifier(prop.argument)) {
|
|
14623
|
+
ids.push({ kind: "Identifier", name: prop.argument.name });
|
|
14624
|
+
} else if (t.isPatternLike(prop.argument)) {
|
|
14625
|
+
ids.push(...extractIdentifiersFromPattern(prop.argument));
|
|
14626
|
+
}
|
|
14615
14627
|
}
|
|
14616
14628
|
}
|
|
14617
14629
|
} else if (t.isArrayPattern(pattern)) {
|
|
@@ -14619,16 +14631,20 @@ function extractIdentifiersFromPattern(pattern) {
|
|
|
14619
14631
|
if (!elem) continue;
|
|
14620
14632
|
if (t.isIdentifier(elem)) {
|
|
14621
14633
|
ids.push({ kind: "Identifier", name: elem.name });
|
|
14622
|
-
} else if (t.
|
|
14634
|
+
} else if (t.isRestElement(elem)) {
|
|
14635
|
+
if (t.isIdentifier(elem.argument)) {
|
|
14636
|
+
ids.push({ kind: "Identifier", name: elem.argument.name });
|
|
14637
|
+
} else if (t.isPatternLike(elem.argument)) {
|
|
14638
|
+
ids.push(...extractIdentifiersFromPattern(elem.argument));
|
|
14639
|
+
}
|
|
14640
|
+
} else if (t.isPatternLike(elem)) {
|
|
14623
14641
|
ids.push(...extractIdentifiersFromPattern(elem));
|
|
14624
|
-
} else if (t.isRestElement(elem) && t.isIdentifier(elem.argument)) {
|
|
14625
|
-
ids.push({ kind: "Identifier", name: elem.argument.name });
|
|
14626
14642
|
}
|
|
14627
14643
|
}
|
|
14628
14644
|
} else if (t.isAssignmentPattern(pattern)) {
|
|
14629
14645
|
if (t.isIdentifier(pattern.left)) {
|
|
14630
14646
|
ids.push({ kind: "Identifier", name: pattern.left.name });
|
|
14631
|
-
} else if (t.
|
|
14647
|
+
} else if (t.isPatternLike(pattern.left)) {
|
|
14632
14648
|
ids.push(...extractIdentifiersFromPattern(pattern.left));
|
|
14633
14649
|
}
|
|
14634
14650
|
}
|
|
@@ -14814,8 +14830,12 @@ function convertFunction(name, params, body, options) {
|
|
|
14814
14830
|
} else if (t.isObjectPattern(p.left) || t.isArrayPattern(p.left)) {
|
|
14815
14831
|
paramIds.push(...extractIdentifiersFromPattern(p.left));
|
|
14816
14832
|
}
|
|
14817
|
-
} else if (t.isRestElement(p)
|
|
14818
|
-
|
|
14833
|
+
} else if (t.isRestElement(p)) {
|
|
14834
|
+
if (t.isIdentifier(p.argument)) {
|
|
14835
|
+
paramIds.push({ kind: "Identifier", name: p.argument.name });
|
|
14836
|
+
} else if (t.isPattern(p.argument)) {
|
|
14837
|
+
paramIds.push(...extractIdentifiersFromPattern(p.argument));
|
|
14838
|
+
}
|
|
14819
14839
|
}
|
|
14820
14840
|
}
|
|
14821
14841
|
const bodyStatements = [...body];
|
|
@@ -14900,8 +14920,21 @@ function convertFunction(name, params, body, options) {
|
|
|
14900
14920
|
const excludeKeys = [];
|
|
14901
14921
|
decl.id.properties.forEach((prop) => {
|
|
14902
14922
|
if (t.isObjectProperty(prop)) {
|
|
14923
|
+
if (prop.computed) {
|
|
14924
|
+
reportUnsupportedExpression(
|
|
14925
|
+
prop.key,
|
|
14926
|
+
"Computed keys in object destructuring are not supported in HIR conversion."
|
|
14927
|
+
);
|
|
14928
|
+
return;
|
|
14929
|
+
}
|
|
14903
14930
|
const keyName = t.isIdentifier(prop.key) ? prop.key.name : t.isStringLiteral(prop.key) ? prop.key.value : t.isNumericLiteral(prop.key) ? String(prop.key.value) : null;
|
|
14904
|
-
if (!keyName)
|
|
14931
|
+
if (!keyName) {
|
|
14932
|
+
reportUnsupportedExpression(
|
|
14933
|
+
prop.key,
|
|
14934
|
+
"Unsupported object destructuring key in HIR conversion."
|
|
14935
|
+
);
|
|
14936
|
+
return;
|
|
14937
|
+
}
|
|
14905
14938
|
excludeKeys.push(t.stringLiteral(keyName));
|
|
14906
14939
|
if (t.isIdentifier(prop.value)) {
|
|
14907
14940
|
const memberExpr = t.memberExpression(
|
|
@@ -14915,8 +14948,21 @@ function convertFunction(name, params, body, options) {
|
|
|
14915
14948
|
value: convertExpression(memberExpr),
|
|
14916
14949
|
declarationKind: declKind
|
|
14917
14950
|
});
|
|
14951
|
+
} else {
|
|
14952
|
+
reportUnsupportedExpression(
|
|
14953
|
+
prop.value,
|
|
14954
|
+
"Unsupported object destructuring pattern in HIR conversion."
|
|
14955
|
+
);
|
|
14956
|
+
return;
|
|
14957
|
+
}
|
|
14958
|
+
} else if (t.isRestElement(prop)) {
|
|
14959
|
+
if (!t.isIdentifier(prop.argument)) {
|
|
14960
|
+
reportUnsupportedExpression(
|
|
14961
|
+
prop.argument,
|
|
14962
|
+
"Rest destructuring patterns must be identifiers in HIR conversion."
|
|
14963
|
+
);
|
|
14964
|
+
return;
|
|
14918
14965
|
}
|
|
14919
|
-
} else if (t.isRestElement(prop) && t.isIdentifier(prop.argument)) {
|
|
14920
14966
|
const restExpr = t.callExpression(t.identifier("__fictPropsRest"), [
|
|
14921
14967
|
useTemp ? t.identifier(tempName) : babelSourceExpr,
|
|
14922
14968
|
t.arrayExpression(excludeKeys)
|
|
@@ -14927,6 +14973,12 @@ function convertFunction(name, params, body, options) {
|
|
|
14927
14973
|
value: convertExpression(restExpr),
|
|
14928
14974
|
declarationKind: declKind
|
|
14929
14975
|
});
|
|
14976
|
+
} else {
|
|
14977
|
+
reportUnsupportedExpression(
|
|
14978
|
+
prop,
|
|
14979
|
+
"Unsupported object destructuring property in HIR conversion."
|
|
14980
|
+
);
|
|
14981
|
+
return;
|
|
14930
14982
|
}
|
|
14931
14983
|
});
|
|
14932
14984
|
}
|
|
@@ -14952,7 +15004,14 @@ function convertFunction(name, params, body, options) {
|
|
|
14952
15004
|
value: convertExpression(memberExpr),
|
|
14953
15005
|
declarationKind: declKind
|
|
14954
15006
|
});
|
|
14955
|
-
} else if (t.isRestElement(elem)
|
|
15007
|
+
} else if (t.isRestElement(elem)) {
|
|
15008
|
+
if (!t.isIdentifier(elem.argument)) {
|
|
15009
|
+
reportUnsupportedExpression(
|
|
15010
|
+
elem.argument,
|
|
15011
|
+
"Rest destructuring patterns must be identifiers in HIR conversion."
|
|
15012
|
+
);
|
|
15013
|
+
return;
|
|
15014
|
+
}
|
|
14956
15015
|
const sliceCall = t.callExpression(
|
|
14957
15016
|
t.memberExpression(t.identifier(tempName), t.identifier("slice")),
|
|
14958
15017
|
[t.numericLiteral(index)]
|
|
@@ -14963,6 +15022,12 @@ function convertFunction(name, params, body, options) {
|
|
|
14963
15022
|
value: convertExpression(sliceCall),
|
|
14964
15023
|
declarationKind: declKind
|
|
14965
15024
|
});
|
|
15025
|
+
} else {
|
|
15026
|
+
reportUnsupportedExpression(
|
|
15027
|
+
elem,
|
|
15028
|
+
"Unsupported array destructuring pattern in HIR conversion."
|
|
15029
|
+
);
|
|
15030
|
+
return;
|
|
14966
15031
|
}
|
|
14967
15032
|
});
|
|
14968
15033
|
}
|
|
@@ -15125,11 +15190,15 @@ function convertFunction(name, params, body, options) {
|
|
|
15125
15190
|
if (t.isSwitchStatement(stmt)) {
|
|
15126
15191
|
const exitBlock = createBlock();
|
|
15127
15192
|
blocks.push(exitBlock.block);
|
|
15193
|
+
const caseBlocks = stmt.cases.map(() => createBlock());
|
|
15194
|
+
for (const caseBlock of caseBlocks) {
|
|
15195
|
+
blocks.push(caseBlock.block);
|
|
15196
|
+
}
|
|
15128
15197
|
const cases = [];
|
|
15129
15198
|
let defaultTarget;
|
|
15130
|
-
for (
|
|
15131
|
-
const
|
|
15132
|
-
|
|
15199
|
+
for (let index = 0; index < stmt.cases.length; index++) {
|
|
15200
|
+
const switchCase = stmt.cases[index];
|
|
15201
|
+
const caseBlock = caseBlocks[index];
|
|
15133
15202
|
if (switchCase.test) {
|
|
15134
15203
|
cases.push({
|
|
15135
15204
|
test: convertExpression(switchCase.test),
|
|
@@ -15138,20 +15207,26 @@ function convertFunction(name, params, body, options) {
|
|
|
15138
15207
|
} else {
|
|
15139
15208
|
defaultTarget = caseBlock.block.id;
|
|
15140
15209
|
}
|
|
15210
|
+
}
|
|
15211
|
+
cfgContext.loopStack.push({
|
|
15212
|
+
breakTarget: exitBlock.block.id
|
|
15213
|
+
});
|
|
15214
|
+
for (let index = 0; index < stmt.cases.length; index++) {
|
|
15215
|
+
const switchCase = stmt.cases[index];
|
|
15216
|
+
const caseBlock = caseBlocks[index];
|
|
15217
|
+
const nextCaseBlock = caseBlocks[index + 1];
|
|
15218
|
+
const fallthroughTarget = nextCaseBlock ? nextCaseBlock.block.id : exitBlock.block.id;
|
|
15141
15219
|
let caseBuilder = caseBlock;
|
|
15142
15220
|
for (const s of switchCase.consequent) {
|
|
15143
|
-
if (
|
|
15144
|
-
caseBuilder.block.terminator = { kind: "Jump", target: exitBlock.block.id };
|
|
15145
|
-
caseBuilder.sealed = true;
|
|
15146
|
-
break;
|
|
15147
|
-
}
|
|
15221
|
+
if (caseBuilder.sealed) break;
|
|
15148
15222
|
caseBuilder = processStatement(s, caseBuilder, exitBlock.block.id, cfgContext);
|
|
15149
15223
|
}
|
|
15150
15224
|
if (!caseBuilder.sealed) {
|
|
15151
|
-
caseBuilder.block.terminator = { kind: "Jump", target:
|
|
15225
|
+
caseBuilder.block.terminator = { kind: "Jump", target: fallthroughTarget };
|
|
15152
15226
|
caseBuilder.sealed = true;
|
|
15153
15227
|
}
|
|
15154
15228
|
}
|
|
15229
|
+
cfgContext.loopStack.pop();
|
|
15155
15230
|
if (defaultTarget === void 0) {
|
|
15156
15231
|
cases.push({ target: exitBlock.block.id });
|
|
15157
15232
|
} else {
|
|
@@ -15284,6 +15359,10 @@ function convertFunction(name, params, body, options) {
|
|
|
15284
15359
|
current = exitBlock;
|
|
15285
15360
|
continue;
|
|
15286
15361
|
}
|
|
15362
|
+
current = processStatement(stmt, current, current.block.id, cfgContext);
|
|
15363
|
+
if (current.sealed) {
|
|
15364
|
+
current = startNewBlock();
|
|
15365
|
+
}
|
|
15287
15366
|
}
|
|
15288
15367
|
if (!current.sealed) {
|
|
15289
15368
|
current.block.terminator = { kind: "Unreachable" };
|
|
@@ -15370,6 +15449,30 @@ function handleExpressionStatement(expr, push) {
|
|
|
15370
15449
|
}
|
|
15371
15450
|
return false;
|
|
15372
15451
|
}
|
|
15452
|
+
function findBreakContext(ctx, label) {
|
|
15453
|
+
if (label) {
|
|
15454
|
+
for (let i = ctx.loopStack.length - 1; i >= 0; i--) {
|
|
15455
|
+
const entry = ctx.loopStack[i];
|
|
15456
|
+
if (entry?.label === label) return entry;
|
|
15457
|
+
}
|
|
15458
|
+
return void 0;
|
|
15459
|
+
}
|
|
15460
|
+
return ctx.loopStack[ctx.loopStack.length - 1];
|
|
15461
|
+
}
|
|
15462
|
+
function findContinueContext(ctx, label) {
|
|
15463
|
+
if (label) {
|
|
15464
|
+
for (let i = ctx.loopStack.length - 1; i >= 0; i--) {
|
|
15465
|
+
const entry = ctx.loopStack[i];
|
|
15466
|
+
if (entry?.label === label && entry.continueTarget !== void 0) return entry;
|
|
15467
|
+
}
|
|
15468
|
+
return void 0;
|
|
15469
|
+
}
|
|
15470
|
+
for (let i = ctx.loopStack.length - 1; i >= 0; i--) {
|
|
15471
|
+
const entry = ctx.loopStack[i];
|
|
15472
|
+
if (entry?.continueTarget !== void 0) return entry;
|
|
15473
|
+
}
|
|
15474
|
+
return void 0;
|
|
15475
|
+
}
|
|
15373
15476
|
function fillStatements(stmt, bb, jumpTarget, ctx) {
|
|
15374
15477
|
if (t.isBlockStatement(stmt)) {
|
|
15375
15478
|
let current = bb;
|
|
@@ -15395,8 +15498,50 @@ function fillStatements(stmt, bb, jumpTarget, ctx) {
|
|
|
15395
15498
|
}
|
|
15396
15499
|
return result;
|
|
15397
15500
|
}
|
|
15398
|
-
function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
15501
|
+
function processStatement(stmt, bb, jumpTarget, ctx, labelOverride) {
|
|
15399
15502
|
const push = (instr) => bb.block.instructions.push(instr);
|
|
15503
|
+
if (t.isLabeledStatement(stmt) && ctx) {
|
|
15504
|
+
const label = stmt.label.name;
|
|
15505
|
+
const body = stmt.body;
|
|
15506
|
+
if (t.isWhileStatement(body) || t.isForStatement(body) || t.isDoWhileStatement(body) || t.isForInStatement(body) || t.isForOfStatement(body) || t.isSwitchStatement(body)) {
|
|
15507
|
+
return processStatement(body, bb, jumpTarget, ctx, label);
|
|
15508
|
+
}
|
|
15509
|
+
ctx.loopStack.push({
|
|
15510
|
+
breakTarget: jumpTarget,
|
|
15511
|
+
label
|
|
15512
|
+
});
|
|
15513
|
+
try {
|
|
15514
|
+
return processStatement(body, bb, jumpTarget, ctx);
|
|
15515
|
+
} finally {
|
|
15516
|
+
ctx.loopStack.pop();
|
|
15517
|
+
}
|
|
15518
|
+
}
|
|
15519
|
+
if (t.isEmptyStatement(stmt)) {
|
|
15520
|
+
return bb;
|
|
15521
|
+
}
|
|
15522
|
+
if (t.isBlockStatement(stmt)) {
|
|
15523
|
+
const shouldScopeLabel = !!labelOverride && !!ctx;
|
|
15524
|
+
if (shouldScopeLabel) {
|
|
15525
|
+
ctx.loopStack.push({
|
|
15526
|
+
breakTarget: jumpTarget,
|
|
15527
|
+
label: labelOverride
|
|
15528
|
+
});
|
|
15529
|
+
}
|
|
15530
|
+
let current = bb;
|
|
15531
|
+
try {
|
|
15532
|
+
for (const inner of stmt.body) {
|
|
15533
|
+
current = processStatement(inner, current, jumpTarget, ctx);
|
|
15534
|
+
if (current.sealed) {
|
|
15535
|
+
return current;
|
|
15536
|
+
}
|
|
15537
|
+
}
|
|
15538
|
+
return current;
|
|
15539
|
+
} finally {
|
|
15540
|
+
if (shouldScopeLabel) {
|
|
15541
|
+
ctx.loopStack.pop();
|
|
15542
|
+
}
|
|
15543
|
+
}
|
|
15544
|
+
}
|
|
15400
15545
|
if (t.isExpressionStatement(stmt)) {
|
|
15401
15546
|
if (!handleExpressionStatement(stmt.expression, push)) {
|
|
15402
15547
|
push({ kind: "Expression", value: convertExpression(stmt.expression) });
|
|
@@ -15511,6 +15656,21 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15511
15656
|
});
|
|
15512
15657
|
return bb;
|
|
15513
15658
|
}
|
|
15659
|
+
if (t.isClassDeclaration(stmt) && stmt.id) {
|
|
15660
|
+
const classExpr = t.classExpression(
|
|
15661
|
+
stmt.id,
|
|
15662
|
+
stmt.superClass,
|
|
15663
|
+
stmt.body,
|
|
15664
|
+
stmt.decorators ?? null
|
|
15665
|
+
);
|
|
15666
|
+
push({
|
|
15667
|
+
kind: "Assign",
|
|
15668
|
+
target: { kind: "Identifier", name: stmt.id.name },
|
|
15669
|
+
value: convertExpression(classExpr),
|
|
15670
|
+
declarationKind: "let"
|
|
15671
|
+
});
|
|
15672
|
+
return bb;
|
|
15673
|
+
}
|
|
15514
15674
|
if (t.isReturnStatement(stmt)) {
|
|
15515
15675
|
bb.block.terminator = {
|
|
15516
15676
|
kind: "Return",
|
|
@@ -15529,7 +15689,7 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15529
15689
|
}
|
|
15530
15690
|
if (t.isBreakStatement(stmt) && ctx) {
|
|
15531
15691
|
const label = stmt.label?.name;
|
|
15532
|
-
const loopCtx =
|
|
15692
|
+
const loopCtx = findBreakContext(ctx, label);
|
|
15533
15693
|
if (loopCtx) {
|
|
15534
15694
|
bb.block.terminator = { kind: "Break", target: loopCtx.breakTarget, label };
|
|
15535
15695
|
bb.sealed = true;
|
|
@@ -15541,7 +15701,7 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15541
15701
|
}
|
|
15542
15702
|
if (t.isContinueStatement(stmt) && ctx) {
|
|
15543
15703
|
const label = stmt.label?.name;
|
|
15544
|
-
const loopCtx =
|
|
15704
|
+
const loopCtx = findContinueContext(ctx, label);
|
|
15545
15705
|
if (loopCtx) {
|
|
15546
15706
|
bb.block.terminator = { kind: "Continue", target: loopCtx.continueTarget, label };
|
|
15547
15707
|
bb.sealed = true;
|
|
@@ -15590,7 +15750,8 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15590
15750
|
condBlock.sealed = true;
|
|
15591
15751
|
ctx.loopStack.push({
|
|
15592
15752
|
breakTarget: exitBlock.block.id,
|
|
15593
|
-
continueTarget: condBlock.block.id
|
|
15753
|
+
continueTarget: condBlock.block.id,
|
|
15754
|
+
label: labelOverride
|
|
15594
15755
|
});
|
|
15595
15756
|
fillStatements(stmt.body, bodyBlock, condBlock.block.id, ctx);
|
|
15596
15757
|
ctx.loopStack.pop();
|
|
@@ -15635,8 +15796,9 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15635
15796
|
condBlock.sealed = true;
|
|
15636
15797
|
ctx.loopStack.push({
|
|
15637
15798
|
breakTarget: exitBlock.block.id,
|
|
15638
|
-
continueTarget: updateBlock.block.id
|
|
15799
|
+
continueTarget: updateBlock.block.id,
|
|
15639
15800
|
// continue goes to update in for loop
|
|
15801
|
+
label: labelOverride
|
|
15640
15802
|
});
|
|
15641
15803
|
fillStatements(stmt.body, bodyBlock, updateBlock.block.id, ctx);
|
|
15642
15804
|
ctx.loopStack.pop();
|
|
@@ -15659,7 +15821,8 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15659
15821
|
bb.sealed = true;
|
|
15660
15822
|
ctx.loopStack.push({
|
|
15661
15823
|
breakTarget: exitBlock.block.id,
|
|
15662
|
-
continueTarget: condBlock.block.id
|
|
15824
|
+
continueTarget: condBlock.block.id,
|
|
15825
|
+
label: labelOverride
|
|
15663
15826
|
});
|
|
15664
15827
|
fillStatements(stmt.body, bodyBlock, condBlock.block.id, ctx);
|
|
15665
15828
|
ctx.loopStack.pop();
|
|
@@ -15707,7 +15870,8 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15707
15870
|
bb.sealed = true;
|
|
15708
15871
|
ctx.loopStack.push({
|
|
15709
15872
|
breakTarget: exitBlock.block.id,
|
|
15710
|
-
continueTarget: bodyBlock.block.id
|
|
15873
|
+
continueTarget: bodyBlock.block.id,
|
|
15874
|
+
label: labelOverride
|
|
15711
15875
|
});
|
|
15712
15876
|
fillStatements(stmt.body, bodyBlock, exitBlock.block.id, ctx);
|
|
15713
15877
|
ctx.loopStack.pop();
|
|
@@ -15747,7 +15911,8 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15747
15911
|
bb.sealed = true;
|
|
15748
15912
|
ctx.loopStack.push({
|
|
15749
15913
|
breakTarget: exitBlock.block.id,
|
|
15750
|
-
continueTarget: bodyBlock.block.id
|
|
15914
|
+
continueTarget: bodyBlock.block.id,
|
|
15915
|
+
label: labelOverride
|
|
15751
15916
|
});
|
|
15752
15917
|
fillStatements(stmt.body, bodyBlock, exitBlock.block.id, ctx);
|
|
15753
15918
|
ctx.loopStack.pop();
|
|
@@ -15756,11 +15921,15 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15756
15921
|
if (t.isSwitchStatement(stmt) && ctx) {
|
|
15757
15922
|
const exitBlock = ctx.createBlock();
|
|
15758
15923
|
ctx.blocks.push(exitBlock.block);
|
|
15924
|
+
const caseBlocks = stmt.cases.map(() => ctx.createBlock());
|
|
15925
|
+
for (const caseBlock of caseBlocks) {
|
|
15926
|
+
ctx.blocks.push(caseBlock.block);
|
|
15927
|
+
}
|
|
15759
15928
|
const cases = [];
|
|
15760
15929
|
let defaultTarget;
|
|
15761
|
-
for (
|
|
15762
|
-
const
|
|
15763
|
-
|
|
15930
|
+
for (let index = 0; index < stmt.cases.length; index++) {
|
|
15931
|
+
const switchCase = stmt.cases[index];
|
|
15932
|
+
const caseBlock = caseBlocks[index];
|
|
15764
15933
|
if (switchCase.test) {
|
|
15765
15934
|
cases.push({
|
|
15766
15935
|
test: convertExpression(switchCase.test),
|
|
@@ -15769,20 +15938,27 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15769
15938
|
} else {
|
|
15770
15939
|
defaultTarget = caseBlock.block.id;
|
|
15771
15940
|
}
|
|
15941
|
+
}
|
|
15942
|
+
ctx.loopStack.push({
|
|
15943
|
+
breakTarget: exitBlock.block.id,
|
|
15944
|
+
label: labelOverride
|
|
15945
|
+
});
|
|
15946
|
+
for (let index = 0; index < stmt.cases.length; index++) {
|
|
15947
|
+
const switchCase = stmt.cases[index];
|
|
15948
|
+
const caseBlock = caseBlocks[index];
|
|
15949
|
+
const nextCaseBlock = caseBlocks[index + 1];
|
|
15950
|
+
const fallthroughTarget = nextCaseBlock ? nextCaseBlock.block.id : exitBlock.block.id;
|
|
15772
15951
|
let current = caseBlock;
|
|
15773
15952
|
for (const s of switchCase.consequent) {
|
|
15774
|
-
if (
|
|
15775
|
-
current.block.terminator = { kind: "Jump", target: exitBlock.block.id };
|
|
15776
|
-
current.sealed = true;
|
|
15777
|
-
break;
|
|
15778
|
-
}
|
|
15953
|
+
if (current.sealed) break;
|
|
15779
15954
|
current = processStatement(s, current, exitBlock.block.id, ctx);
|
|
15780
15955
|
}
|
|
15781
15956
|
if (!current.sealed) {
|
|
15782
|
-
current.block.terminator = { kind: "Jump", target:
|
|
15957
|
+
current.block.terminator = { kind: "Jump", target: fallthroughTarget };
|
|
15783
15958
|
current.sealed = true;
|
|
15784
15959
|
}
|
|
15785
15960
|
}
|
|
15961
|
+
ctx.loopStack.pop();
|
|
15786
15962
|
if (defaultTarget === void 0) {
|
|
15787
15963
|
cases.push({ target: exitBlock.block.id });
|
|
15788
15964
|
} else {
|
|
@@ -15831,30 +16007,41 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15831
16007
|
}
|
|
15832
16008
|
return exitBlock;
|
|
15833
16009
|
}
|
|
15834
|
-
|
|
15835
|
-
bb.block.
|
|
15836
|
-
|
|
15837
|
-
}
|
|
15838
|
-
return bb;
|
|
16010
|
+
throw new HIRError(`Unsupported statement in HIR lowering: ${stmt.type}`, "BUILD_ERROR", {
|
|
16011
|
+
blockId: bb.block.id
|
|
16012
|
+
});
|
|
15839
16013
|
}
|
|
15840
16014
|
function convertExpression(node, options) {
|
|
15841
16015
|
const loc = getLoc(node);
|
|
15842
|
-
const convertCallArguments = (args, reactiveScope) =>
|
|
15843
|
-
|
|
15844
|
-
|
|
15845
|
-
|
|
15846
|
-
|
|
15847
|
-
|
|
15848
|
-
|
|
15849
|
-
|
|
15850
|
-
|
|
15851
|
-
|
|
15852
|
-
|
|
16016
|
+
const convertCallArguments = (args, reactiveScope) => {
|
|
16017
|
+
const converted = [];
|
|
16018
|
+
for (const arg of args) {
|
|
16019
|
+
if (t.isSpreadElement(arg)) {
|
|
16020
|
+
converted.push({
|
|
16021
|
+
kind: "SpreadElement",
|
|
16022
|
+
argument: convertExpression(arg.argument),
|
|
16023
|
+
loc: getLoc(arg)
|
|
16024
|
+
});
|
|
16025
|
+
continue;
|
|
16026
|
+
}
|
|
16027
|
+
if (t.isExpression(arg)) {
|
|
16028
|
+
if (reactiveScope && arg === args[0] && (t.isArrowFunctionExpression(arg) || t.isFunctionExpression(arg))) {
|
|
16029
|
+
converted.push(convertExpression(arg, { reactiveScope }));
|
|
16030
|
+
continue;
|
|
16031
|
+
}
|
|
16032
|
+
converted.push(convertExpression(arg));
|
|
16033
|
+
continue;
|
|
16034
|
+
}
|
|
16035
|
+
if (t.isArgumentPlaceholder?.(arg)) {
|
|
16036
|
+
return reportUnsupportedExpression(
|
|
16037
|
+
arg,
|
|
16038
|
+
"Argument placeholders are not supported in HIR conversion."
|
|
16039
|
+
);
|
|
15853
16040
|
}
|
|
15854
|
-
return
|
|
16041
|
+
return reportUnsupportedExpression(arg, "Unsupported call argument in HIR conversion.");
|
|
15855
16042
|
}
|
|
15856
|
-
return
|
|
15857
|
-
}
|
|
16043
|
+
return converted;
|
|
16044
|
+
};
|
|
15858
16045
|
const resolveReactiveScope = (callee) => {
|
|
15859
16046
|
const reactiveScopes = activeBuildOptions?.reactiveScopes;
|
|
15860
16047
|
if (!reactiveScopes || reactiveScopes.size === 0) return void 0;
|
|
@@ -15866,6 +16053,9 @@ function convertExpression(node, options) {
|
|
|
15866
16053
|
}
|
|
15867
16054
|
return void 0;
|
|
15868
16055
|
};
|
|
16056
|
+
if (t.isChainExpression?.(node) || node.type === "ChainExpression") {
|
|
16057
|
+
return convertExpression(node.expression, options);
|
|
16058
|
+
}
|
|
15869
16059
|
if (t.isParenthesizedExpression(node) && t.isExpression(node.expression)) {
|
|
15870
16060
|
return convertExpression(node.expression);
|
|
15871
16061
|
}
|
|
@@ -15923,7 +16113,13 @@ function convertExpression(node, options) {
|
|
|
15923
16113
|
return call;
|
|
15924
16114
|
}
|
|
15925
16115
|
if (t.isMemberExpression(node) || t.isOptionalMemberExpression(node)) {
|
|
15926
|
-
|
|
16116
|
+
if (t.isPrivateName(node.property)) {
|
|
16117
|
+
return reportUnsupportedExpression(
|
|
16118
|
+
node.property,
|
|
16119
|
+
"Private field access is not supported in HIR conversion."
|
|
16120
|
+
);
|
|
16121
|
+
}
|
|
16122
|
+
const propertyNode = node.property;
|
|
15927
16123
|
const isOptional = t.isOptionalMemberExpression(node);
|
|
15928
16124
|
const object = convertExpression(node.object);
|
|
15929
16125
|
const property = t.isExpression(propertyNode) ? convertExpression(propertyNode) : { kind: "Literal", value: void 0 };
|
|
@@ -15989,67 +16185,106 @@ function convertExpression(node, options) {
|
|
|
15989
16185
|
return cond;
|
|
15990
16186
|
}
|
|
15991
16187
|
if (t.isArrayExpression(node)) {
|
|
16188
|
+
if ((node.elements ?? []).some((el) => el == null)) {
|
|
16189
|
+
return reportUnsupportedExpression(
|
|
16190
|
+
node,
|
|
16191
|
+
"Array literal holes are not supported in HIR conversion. Use explicit undefined values instead."
|
|
16192
|
+
);
|
|
16193
|
+
}
|
|
16194
|
+
const elements = [];
|
|
16195
|
+
for (const el of node.elements ?? []) {
|
|
16196
|
+
if (!el) continue;
|
|
16197
|
+
if (t.isSpreadElement(el)) {
|
|
16198
|
+
elements.push({
|
|
16199
|
+
kind: "SpreadElement",
|
|
16200
|
+
argument: convertExpression(el.argument),
|
|
16201
|
+
loc: getLoc(el)
|
|
16202
|
+
});
|
|
16203
|
+
continue;
|
|
16204
|
+
}
|
|
16205
|
+
if (t.isExpression(el)) {
|
|
16206
|
+
elements.push(convertExpression(el));
|
|
16207
|
+
continue;
|
|
16208
|
+
}
|
|
16209
|
+
return reportUnsupportedExpression(el, "Unsupported array literal element in HIR conversion.");
|
|
16210
|
+
}
|
|
15992
16211
|
const arr = {
|
|
15993
16212
|
kind: "ArrayExpression",
|
|
15994
|
-
elements
|
|
15995
|
-
if (!el) return void 0;
|
|
15996
|
-
if (t.isSpreadElement(el)) {
|
|
15997
|
-
return {
|
|
15998
|
-
kind: "SpreadElement",
|
|
15999
|
-
argument: convertExpression(el.argument),
|
|
16000
|
-
loc: getLoc(el)
|
|
16001
|
-
};
|
|
16002
|
-
}
|
|
16003
|
-
if (t.isExpression(el)) return convertExpression(el);
|
|
16004
|
-
return void 0;
|
|
16005
|
-
}).filter(Boolean),
|
|
16213
|
+
elements,
|
|
16006
16214
|
loc
|
|
16007
16215
|
};
|
|
16008
16216
|
return arr;
|
|
16009
16217
|
}
|
|
16010
16218
|
if (t.isObjectExpression(node)) {
|
|
16219
|
+
const properties = [];
|
|
16011
16220
|
const obj = {
|
|
16012
16221
|
kind: "ObjectExpression",
|
|
16013
|
-
properties
|
|
16014
|
-
|
|
16015
|
-
|
|
16016
|
-
|
|
16017
|
-
|
|
16018
|
-
|
|
16019
|
-
|
|
16222
|
+
properties,
|
|
16223
|
+
loc
|
|
16224
|
+
};
|
|
16225
|
+
for (const prop of node.properties) {
|
|
16226
|
+
if (t.isSpreadElement(prop)) {
|
|
16227
|
+
properties.push({
|
|
16228
|
+
kind: "SpreadElement",
|
|
16229
|
+
argument: convertExpression(prop.argument),
|
|
16230
|
+
loc: getLoc(prop)
|
|
16231
|
+
});
|
|
16232
|
+
continue;
|
|
16233
|
+
}
|
|
16234
|
+
if (t.isObjectMethod(prop)) {
|
|
16235
|
+
const keyExpr = prop.computed ? t.isExpression(prop.key) ? convertExpression(prop.key) : void 0 : 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 } : t.isBigIntLiteral(prop.key) ? { kind: "Literal", value: BigInt(prop.key.value) } : void 0;
|
|
16236
|
+
if (!keyExpr) {
|
|
16237
|
+
return reportUnsupportedExpression(
|
|
16238
|
+
prop.key,
|
|
16239
|
+
"Unsupported object literal key in HIR conversion."
|
|
16240
|
+
);
|
|
16020
16241
|
}
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
|
|
16024
|
-
|
|
16025
|
-
|
|
16026
|
-
|
|
16027
|
-
|
|
16028
|
-
|
|
16029
|
-
|
|
16030
|
-
|
|
16242
|
+
const fnExpr = t.functionExpression(
|
|
16243
|
+
null,
|
|
16244
|
+
prop.params,
|
|
16245
|
+
prop.body,
|
|
16246
|
+
prop.generator,
|
|
16247
|
+
prop.async
|
|
16248
|
+
);
|
|
16249
|
+
properties.push({
|
|
16250
|
+
kind: "Property",
|
|
16251
|
+
key: keyExpr,
|
|
16252
|
+
value: convertExpression(fnExpr),
|
|
16253
|
+
computed: prop.computed,
|
|
16254
|
+
propertyKind: prop.kind ?? "method",
|
|
16255
|
+
loc: getLoc(prop)
|
|
16256
|
+
});
|
|
16257
|
+
continue;
|
|
16258
|
+
}
|
|
16259
|
+
if (t.isObjectProperty(prop)) {
|
|
16260
|
+
const keyExpr = prop.computed ? t.isExpression(prop.key) ? convertExpression(prop.key) : void 0 : 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 } : t.isBigIntLiteral(prop.key) ? { kind: "Literal", value: BigInt(prop.key.value) } : void 0;
|
|
16261
|
+
if (!keyExpr) {
|
|
16262
|
+
return reportUnsupportedExpression(
|
|
16263
|
+
prop.key,
|
|
16264
|
+
"Unsupported object literal key in HIR conversion."
|
|
16031
16265
|
);
|
|
16032
|
-
return {
|
|
16033
|
-
kind: "Property",
|
|
16034
|
-
key: keyExpr2,
|
|
16035
|
-
value: convertExpression(fnExpr),
|
|
16036
|
-
loc: getLoc(prop)
|
|
16037
|
-
};
|
|
16038
16266
|
}
|
|
16039
|
-
if (!t.
|
|
16040
|
-
|
|
16041
|
-
|
|
16042
|
-
|
|
16043
|
-
|
|
16267
|
+
if (!t.isExpression(prop.value)) {
|
|
16268
|
+
return reportUnsupportedExpression(
|
|
16269
|
+
prop.value,
|
|
16270
|
+
"Unsupported object literal value in HIR conversion."
|
|
16271
|
+
);
|
|
16272
|
+
}
|
|
16273
|
+
properties.push({
|
|
16044
16274
|
kind: "Property",
|
|
16045
16275
|
key: keyExpr,
|
|
16046
16276
|
value: convertExpression(prop.value),
|
|
16277
|
+
computed: prop.computed,
|
|
16047
16278
|
shorthand: prop.shorthand && t.isIdentifier(prop.value),
|
|
16048
16279
|
loc: getLoc(prop)
|
|
16049
|
-
};
|
|
16050
|
-
|
|
16051
|
-
|
|
16052
|
-
|
|
16280
|
+
});
|
|
16281
|
+
continue;
|
|
16282
|
+
}
|
|
16283
|
+
return reportUnsupportedExpression(
|
|
16284
|
+
prop,
|
|
16285
|
+
"Unsupported object literal property in HIR conversion."
|
|
16286
|
+
);
|
|
16287
|
+
}
|
|
16053
16288
|
return obj;
|
|
16054
16289
|
}
|
|
16055
16290
|
if (t.isJSXElement(node)) {
|
|
@@ -16077,6 +16312,11 @@ function convertExpression(node, options) {
|
|
|
16077
16312
|
value: convertJSXElement(child),
|
|
16078
16313
|
loc: getLoc(child)
|
|
16079
16314
|
});
|
|
16315
|
+
} else if (t.isJSXSpreadChild(child)) {
|
|
16316
|
+
return reportUnsupportedExpression(
|
|
16317
|
+
child,
|
|
16318
|
+
"JSX spread children are not supported in HIR conversion."
|
|
16319
|
+
);
|
|
16080
16320
|
} else if (t.isJSXFragment(child)) {
|
|
16081
16321
|
for (const fragChild of child.children) {
|
|
16082
16322
|
if (t.isJSXText(fragChild)) {
|
|
@@ -16098,6 +16338,11 @@ function convertExpression(node, options) {
|
|
|
16098
16338
|
value: convertJSXElement(fragChild),
|
|
16099
16339
|
loc: getLoc(fragChild)
|
|
16100
16340
|
});
|
|
16341
|
+
} else if (t.isJSXSpreadChild(fragChild)) {
|
|
16342
|
+
return reportUnsupportedExpression(
|
|
16343
|
+
fragChild,
|
|
16344
|
+
"JSX spread children are not supported in HIR conversion."
|
|
16345
|
+
);
|
|
16101
16346
|
}
|
|
16102
16347
|
}
|
|
16103
16348
|
}
|
|
@@ -16293,7 +16538,10 @@ function convertJSXElement(node) {
|
|
|
16293
16538
|
tagName = convertJSXMemberExpr(opening.name);
|
|
16294
16539
|
isComponent = true;
|
|
16295
16540
|
} else {
|
|
16296
|
-
|
|
16541
|
+
return reportUnsupportedExpression(
|
|
16542
|
+
opening.name,
|
|
16543
|
+
`Unsupported JSX tag syntax '${opening.name.type}' in HIR conversion`
|
|
16544
|
+
);
|
|
16297
16545
|
}
|
|
16298
16546
|
const attributes = [];
|
|
16299
16547
|
for (const attr of opening.attributes) {
|
|
@@ -16305,17 +16553,33 @@ function convertJSXElement(node) {
|
|
|
16305
16553
|
spreadExpr: convertExpression(attr.argument),
|
|
16306
16554
|
loc: getLoc(attr)
|
|
16307
16555
|
});
|
|
16308
|
-
} else if (t.isJSXAttribute(attr)
|
|
16556
|
+
} else if (t.isJSXAttribute(attr)) {
|
|
16557
|
+
const nameNode = attr.name;
|
|
16558
|
+
let attrName = null;
|
|
16559
|
+
if (t.isJSXIdentifier(attr.name)) {
|
|
16560
|
+
attrName = attr.name.name;
|
|
16561
|
+
} else if (t.isJSXNamespacedName(attr.name)) {
|
|
16562
|
+
attrName = `${attr.name.namespace.name}:${attr.name.name.name}`;
|
|
16563
|
+
} else {
|
|
16564
|
+
return reportUnsupportedExpression(
|
|
16565
|
+
nameNode,
|
|
16566
|
+
"Unsupported JSX attribute name in HIR conversion"
|
|
16567
|
+
);
|
|
16568
|
+
}
|
|
16309
16569
|
let value = null;
|
|
16310
16570
|
if (attr.value) {
|
|
16311
16571
|
if (t.isStringLiteral(attr.value)) {
|
|
16312
16572
|
value = { kind: "Literal", value: attr.value.value, loc: getLoc(attr.value) };
|
|
16313
16573
|
} else if (t.isJSXExpressionContainer(attr.value) && !t.isJSXEmptyExpression(attr.value.expression)) {
|
|
16314
16574
|
value = convertExpression(attr.value.expression);
|
|
16575
|
+
} else if (t.isJSXElement(attr.value)) {
|
|
16576
|
+
value = convertJSXElement(attr.value);
|
|
16577
|
+
} else if (t.isJSXFragment(attr.value)) {
|
|
16578
|
+
value = convertExpression(attr.value);
|
|
16315
16579
|
}
|
|
16316
16580
|
}
|
|
16317
16581
|
attributes.push({
|
|
16318
|
-
name:
|
|
16582
|
+
name: attrName,
|
|
16319
16583
|
value,
|
|
16320
16584
|
loc: getLoc(attr)
|
|
16321
16585
|
});
|
|
@@ -16342,6 +16606,11 @@ function convertJSXElement(node) {
|
|
|
16342
16606
|
value: convertJSXElement(child),
|
|
16343
16607
|
loc: getLoc(child)
|
|
16344
16608
|
});
|
|
16609
|
+
} else if (t.isJSXSpreadChild(child)) {
|
|
16610
|
+
return reportUnsupportedExpression(
|
|
16611
|
+
child,
|
|
16612
|
+
"JSX spread children are not supported in HIR conversion."
|
|
16613
|
+
);
|
|
16345
16614
|
} else if (t.isJSXFragment(child)) {
|
|
16346
16615
|
for (const fragChild of child.children) {
|
|
16347
16616
|
if (t.isJSXText(fragChild)) {
|
|
@@ -16363,6 +16632,11 @@ function convertJSXElement(node) {
|
|
|
16363
16632
|
value: convertJSXElement(fragChild),
|
|
16364
16633
|
loc: getLoc(fragChild)
|
|
16365
16634
|
});
|
|
16635
|
+
} else if (t.isJSXSpreadChild(fragChild)) {
|
|
16636
|
+
return reportUnsupportedExpression(
|
|
16637
|
+
fragChild,
|
|
16638
|
+
"JSX spread children are not supported in HIR conversion."
|
|
16639
|
+
);
|
|
16366
16640
|
}
|
|
16367
16641
|
}
|
|
16368
16642
|
}
|
|
@@ -16598,7 +16872,7 @@ var DiagnosticMessages = {
|
|
|
16598
16872
|
["FICT-R001" /* FICT_R001 */]: "Expression crosses reactive region boundary.",
|
|
16599
16873
|
["FICT-R002" /* FICT_R002 */]: "Scope escape detected, value may not be tracked.",
|
|
16600
16874
|
["FICT-R003" /* FICT_R003 */]: "Expression cannot be memoized automatically.",
|
|
16601
|
-
["FICT-R004" /* FICT_R004 */]: "Reactive creation inside non-JSX control flow
|
|
16875
|
+
["FICT-R004" /* FICT_R004 */]: "Reactive creation inside non-JSX control flow may not auto-dispose in complex paths. Prefer createScope/runInScope (or JSX-managed regions) for explicit lifecycle control.",
|
|
16602
16876
|
["FICT-R005" /* FICT_R005 */]: "Function captures reactive variables from outer scope; pass them as parameters or memoize explicitly to avoid hidden dependencies.",
|
|
16603
16877
|
["FICT-X001" /* FICT_X001 */]: "Object is recreated on each render, consider memoizing.",
|
|
16604
16878
|
["FICT-X002" /* FICT_X002 */]: "Array is recreated on each render, consider memoizing.",
|
|
@@ -16628,7 +16902,7 @@ var DiagnosticSeverities = {
|
|
|
16628
16902
|
["FICT-R001" /* FICT_R001 */]: "info" /* Info */,
|
|
16629
16903
|
["FICT-R002" /* FICT_R002 */]: "warning" /* Warning */,
|
|
16630
16904
|
["FICT-R003" /* FICT_R003 */]: "info" /* Info */,
|
|
16631
|
-
["FICT-R004" /* FICT_R004 */]: "
|
|
16905
|
+
["FICT-R004" /* FICT_R004 */]: "error" /* Error */,
|
|
16632
16906
|
["FICT-R005" /* FICT_R005 */]: "warning" /* Warning */,
|
|
16633
16907
|
["FICT-X001" /* FICT_X001 */]: "hint" /* Hint */,
|
|
16634
16908
|
["FICT-X002" /* FICT_X002 */]: "hint" /* Hint */,
|
|
@@ -17108,7 +17382,11 @@ function rewriteExprWithMap(expr, rewrites) {
|
|
|
17108
17382
|
if (p.kind === "SpreadElement") {
|
|
17109
17383
|
return { ...p, argument: rewriteExprWithMap(p.argument, rewrites) };
|
|
17110
17384
|
}
|
|
17111
|
-
return {
|
|
17385
|
+
return {
|
|
17386
|
+
...p,
|
|
17387
|
+
key: p.computed ? rewriteExprWithMap(p.key, rewrites) : p.key,
|
|
17388
|
+
value: rewriteExprWithMap(p.value, rewrites)
|
|
17389
|
+
};
|
|
17112
17390
|
})
|
|
17113
17391
|
};
|
|
17114
17392
|
case "ImportExpression":
|
|
@@ -17255,7 +17533,11 @@ function toSSA(fn) {
|
|
|
17255
17533
|
if (p.kind === "SpreadElement") {
|
|
17256
17534
|
return { ...p, argument: renameExpr(p.argument) };
|
|
17257
17535
|
}
|
|
17258
|
-
return {
|
|
17536
|
+
return {
|
|
17537
|
+
...p,
|
|
17538
|
+
key: p.computed ? renameExpr(p.key) : p.key,
|
|
17539
|
+
value: renameExpr(p.value)
|
|
17540
|
+
};
|
|
17259
17541
|
})
|
|
17260
17542
|
};
|
|
17261
17543
|
default:
|
|
@@ -18685,16 +18967,104 @@ function structurizeBranchUntilJoin(ctx, block, term, outerJoin) {
|
|
|
18685
18967
|
return ifNode;
|
|
18686
18968
|
}
|
|
18687
18969
|
function structurizeSwitch(ctx, block, term) {
|
|
18970
|
+
const uniqueTargets = Array.from(new Set(term.cases.map((c) => c.target)));
|
|
18971
|
+
const joinBlock = findSwitchJoinBlock(ctx, uniqueTargets);
|
|
18688
18972
|
const cases = [];
|
|
18973
|
+
const emittedBeforeSwitch = new Set(ctx.emitted);
|
|
18974
|
+
const emittedBySwitchCases = /* @__PURE__ */ new Set();
|
|
18689
18975
|
for (const c of term.cases) {
|
|
18690
|
-
const
|
|
18691
|
-
|
|
18976
|
+
const caseCtx = {
|
|
18977
|
+
...ctx,
|
|
18978
|
+
emitted: new Set(emittedBeforeSwitch),
|
|
18979
|
+
processing: new Set(ctx.processing)
|
|
18980
|
+
};
|
|
18981
|
+
const body = joinBlock !== void 0 ? structurizeBlockUntilJoin(caseCtx, c.target, joinBlock) : structurizeBlock(caseCtx, c.target);
|
|
18982
|
+
for (const emittedBlock of caseCtx.emitted) {
|
|
18983
|
+
if (!emittedBeforeSwitch.has(emittedBlock)) {
|
|
18984
|
+
emittedBySwitchCases.add(emittedBlock);
|
|
18985
|
+
}
|
|
18986
|
+
}
|
|
18987
|
+
const normalizedBody = appendSwitchCaseBreak(body);
|
|
18988
|
+
cases.push({ test: c.test ?? null, body: normalizedBody });
|
|
18692
18989
|
}
|
|
18693
|
-
|
|
18990
|
+
for (const emittedBlock of emittedBySwitchCases) {
|
|
18991
|
+
ctx.emitted.add(emittedBlock);
|
|
18992
|
+
}
|
|
18993
|
+
const switchNode = {
|
|
18694
18994
|
kind: "switch",
|
|
18695
18995
|
discriminant: term.discriminant,
|
|
18696
18996
|
cases
|
|
18697
18997
|
};
|
|
18998
|
+
if (joinBlock !== void 0 && !ctx.emitted.has(joinBlock)) {
|
|
18999
|
+
const joinNode = structurizeBlock(ctx, joinBlock);
|
|
19000
|
+
return { kind: "sequence", nodes: [switchNode, joinNode] };
|
|
19001
|
+
}
|
|
19002
|
+
return switchNode;
|
|
19003
|
+
}
|
|
19004
|
+
function findSwitchJoinBlock(ctx, caseTargets) {
|
|
19005
|
+
const uniqueTargets = Array.from(new Set(caseTargets));
|
|
19006
|
+
if (uniqueTargets.length === 0) return void 0;
|
|
19007
|
+
const reachableByCase = uniqueTargets.map(
|
|
19008
|
+
(target) => collectReachableBlocks(ctx, target, /* @__PURE__ */ new Set())
|
|
19009
|
+
);
|
|
19010
|
+
const reachableUnion = /* @__PURE__ */ new Set();
|
|
19011
|
+
for (const set of reachableByCase) {
|
|
19012
|
+
for (const id of set) reachableUnion.add(id);
|
|
19013
|
+
}
|
|
19014
|
+
const minCaseCoverage = uniqueTargets.length > 1 ? 2 : 1;
|
|
19015
|
+
const candidates = [];
|
|
19016
|
+
for (const id of reachableUnion) {
|
|
19017
|
+
if (uniqueTargets.includes(id)) continue;
|
|
19018
|
+
let reachableCases = 0;
|
|
19019
|
+
for (const set of reachableByCase) {
|
|
19020
|
+
if (set.has(id)) reachableCases++;
|
|
19021
|
+
}
|
|
19022
|
+
if (reachableCases < minCaseCoverage) continue;
|
|
19023
|
+
const predecessors = ctx.predecessors.get(id) ?? [];
|
|
19024
|
+
const predecessorCount = predecessors.filter((pred) => reachableUnion.has(pred)).length;
|
|
19025
|
+
candidates.push({
|
|
19026
|
+
id,
|
|
19027
|
+
reachableCases,
|
|
19028
|
+
predecessorCount,
|
|
19029
|
+
isJoinPoint: predecessors.length > 1
|
|
19030
|
+
});
|
|
19031
|
+
}
|
|
19032
|
+
if (candidates.length === 0) return void 0;
|
|
19033
|
+
candidates.sort((a, b) => {
|
|
19034
|
+
if (a.reachableCases !== b.reachableCases) return b.reachableCases - a.reachableCases;
|
|
19035
|
+
if (a.predecessorCount !== b.predecessorCount) return b.predecessorCount - a.predecessorCount;
|
|
19036
|
+
if (a.isJoinPoint !== b.isJoinPoint) return Number(b.isJoinPoint) - Number(a.isJoinPoint);
|
|
19037
|
+
return a.id - b.id;
|
|
19038
|
+
});
|
|
19039
|
+
return candidates[0]?.id;
|
|
19040
|
+
}
|
|
19041
|
+
function appendSwitchCaseBreak(body) {
|
|
19042
|
+
if (isSwitchCaseTerminated(body)) return body;
|
|
19043
|
+
if (body.kind === "sequence") {
|
|
19044
|
+
return { kind: "sequence", nodes: [...body.nodes, { kind: "break" }] };
|
|
19045
|
+
}
|
|
19046
|
+
return { kind: "sequence", nodes: [body, { kind: "break" }] };
|
|
19047
|
+
}
|
|
19048
|
+
function isSwitchCaseTerminated(node) {
|
|
19049
|
+
if (!node) return false;
|
|
19050
|
+
switch (node.kind) {
|
|
19051
|
+
case "return":
|
|
19052
|
+
case "throw":
|
|
19053
|
+
case "break":
|
|
19054
|
+
case "continue":
|
|
19055
|
+
return true;
|
|
19056
|
+
case "sequence":
|
|
19057
|
+
return node.nodes.length > 0 && isSwitchCaseTerminated(node.nodes[node.nodes.length - 1]);
|
|
19058
|
+
case "block":
|
|
19059
|
+
return node.statements.length > 0 && isSwitchCaseTerminated(node.statements[node.statements.length - 1]);
|
|
19060
|
+
case "if":
|
|
19061
|
+
return isSwitchCaseTerminated(node.consequent) && isSwitchCaseTerminated(node.alternate ?? void 0);
|
|
19062
|
+
case "try":
|
|
19063
|
+
if (node.finalizer && isSwitchCaseTerminated(node.finalizer)) return true;
|
|
19064
|
+
return isSwitchCaseTerminated(node.block) && isSwitchCaseTerminated(node.handler?.body ?? void 0);
|
|
19065
|
+
default:
|
|
19066
|
+
return false;
|
|
19067
|
+
}
|
|
18698
19068
|
}
|
|
18699
19069
|
function structurizeForOf(ctx, block, term) {
|
|
18700
19070
|
const body = structurizeBlock(ctx, term.body);
|
|
@@ -18896,6 +19266,7 @@ function resolveKeySet(expr, ctx, shapes) {
|
|
|
18896
19266
|
const values = [];
|
|
18897
19267
|
for (const prop of arg.properties) {
|
|
18898
19268
|
if (prop.kind !== "Property") return null;
|
|
19269
|
+
if (prop.computed) return null;
|
|
18899
19270
|
if (prop.key.kind === "Identifier") {
|
|
18900
19271
|
values.push(prop.key.name);
|
|
18901
19272
|
} else if (prop.key.kind === "Literal") {
|
|
@@ -19295,7 +19666,10 @@ function analyzeExpression(expr, shapes, propertyReads, ctx) {
|
|
|
19295
19666
|
}
|
|
19296
19667
|
analyzeExpression(prop.argument, shapes, propertyReads, ctx);
|
|
19297
19668
|
} else if (prop.kind === "Property") {
|
|
19298
|
-
if (prop.
|
|
19669
|
+
if (prop.computed) {
|
|
19670
|
+
shape.dynamicAccess = true;
|
|
19671
|
+
analyzeExpression(prop.key, shapes, propertyReads, ctx);
|
|
19672
|
+
} else if (prop.key.kind === "Identifier") {
|
|
19299
19673
|
shape.knownKeys.add(prop.key.name);
|
|
19300
19674
|
} else if (prop.key.kind === "Literal" && typeof prop.key.value === "string") {
|
|
19301
19675
|
shape.knownKeys.add(prop.key.value);
|
|
@@ -19535,6 +19909,7 @@ function markEscaping(expr, shapes) {
|
|
|
19535
19909
|
if (prop.kind === "SpreadElement") {
|
|
19536
19910
|
markEscaping(prop.argument, shapes);
|
|
19537
19911
|
} else if (prop.kind === "Property") {
|
|
19912
|
+
if (prop.computed) markEscaping(prop.key, shapes);
|
|
19538
19913
|
markEscaping(prop.value, shapes);
|
|
19539
19914
|
}
|
|
19540
19915
|
}
|
|
@@ -19639,7 +20014,7 @@ function expressionContainsReactiveCreation(expr, memoMacroNames) {
|
|
|
19639
20014
|
return expr.elements.some((el) => el && expressionContainsReactiveCreation(el, memoMacroNames));
|
|
19640
20015
|
case "ObjectExpression":
|
|
19641
20016
|
return expr.properties.some(
|
|
19642
|
-
(prop) => prop.kind === "SpreadElement" ? expressionContainsReactiveCreation(prop.argument, memoMacroNames) : expressionContainsReactiveCreation(prop.value, memoMacroNames)
|
|
20017
|
+
(prop) => prop.kind === "SpreadElement" ? expressionContainsReactiveCreation(prop.argument, memoMacroNames) : prop.computed && expressionContainsReactiveCreation(prop.key, memoMacroNames) || expressionContainsReactiveCreation(prop.value, memoMacroNames)
|
|
19643
20018
|
);
|
|
19644
20019
|
case "ArrowFunction":
|
|
19645
20020
|
if (expr.isExpression) {
|
|
@@ -19925,7 +20300,7 @@ function expressionUsesTracked(expr, ctx) {
|
|
|
19925
20300
|
case "ObjectExpression":
|
|
19926
20301
|
return expr.properties.some((p) => {
|
|
19927
20302
|
if (p.kind === "SpreadElement") return expressionUsesTracked(p.argument, ctx);
|
|
19928
|
-
return expressionUsesTracked(p.value, ctx);
|
|
20303
|
+
return p.computed && expressionUsesTracked(p.key, ctx) || expressionUsesTracked(p.value, ctx);
|
|
19929
20304
|
});
|
|
19930
20305
|
case "TemplateLiteral":
|
|
19931
20306
|
return expr.expressions.some((e) => expressionUsesTracked(e, ctx));
|
|
@@ -20018,6 +20393,16 @@ function lowerStructuredNodeInternal(node, t4, ctx, declaredVars, regionResult)
|
|
|
20018
20393
|
} : void 0;
|
|
20019
20394
|
return lowerNodeWithRegionContext(node, t4, ctx, declaredVars, regionCtx);
|
|
20020
20395
|
}
|
|
20396
|
+
function ensureSwitchCaseBreak(stmts, t4) {
|
|
20397
|
+
if (stmts.length === 0) {
|
|
20398
|
+
return stmts;
|
|
20399
|
+
}
|
|
20400
|
+
const tail = stmts[stmts.length - 1];
|
|
20401
|
+
if (tail && (t4.isBreakStatement(tail) || t4.isReturnStatement(tail) || t4.isThrowStatement(tail) || t4.isContinueStatement(tail))) {
|
|
20402
|
+
return stmts;
|
|
20403
|
+
}
|
|
20404
|
+
return [...stmts, t4.breakStatement()];
|
|
20405
|
+
}
|
|
20021
20406
|
function lowerNodeWithRegionContext(node, t4, ctx, declaredVars, regionCtx) {
|
|
20022
20407
|
switch (node.kind) {
|
|
20023
20408
|
case "sequence": {
|
|
@@ -20207,10 +20592,20 @@ function lowerNodeWithRegionContext(node, t4, ctx, declaredVars, regionCtx) {
|
|
|
20207
20592
|
return [t4.forInStatement(left, right, body)];
|
|
20208
20593
|
}
|
|
20209
20594
|
case "switch": {
|
|
20210
|
-
const
|
|
20211
|
-
|
|
20212
|
-
|
|
20213
|
-
|
|
20595
|
+
const prevConditional = ctx.inConditional ?? 0;
|
|
20596
|
+
ctx.inConditional = prevConditional + 1;
|
|
20597
|
+
let cases;
|
|
20598
|
+
try {
|
|
20599
|
+
cases = node.cases.map((c) => {
|
|
20600
|
+
const stmts = ensureSwitchCaseBreak(
|
|
20601
|
+
lowerNodeWithRegionContext(c.body, t4, ctx, declaredVars, regionCtx),
|
|
20602
|
+
t4
|
|
20603
|
+
);
|
|
20604
|
+
return t4.switchCase(c.test ? lowerExpressionWithDeSSA(c.test, ctx) : null, stmts);
|
|
20605
|
+
});
|
|
20606
|
+
} finally {
|
|
20607
|
+
ctx.inConditional = prevConditional;
|
|
20608
|
+
}
|
|
20214
20609
|
return [t4.switchStatement(lowerExpressionWithDeSSA(node.discriminant, ctx), cases)];
|
|
20215
20610
|
}
|
|
20216
20611
|
case "try": {
|
|
@@ -20499,19 +20894,29 @@ function lowerStructuredNodeForRegion(node, region, t4, ctx, declaredVars, regio
|
|
|
20499
20894
|
return [t4.forInStatement(left, right, t4.blockStatement(body))];
|
|
20500
20895
|
}
|
|
20501
20896
|
case "switch": {
|
|
20502
|
-
const
|
|
20503
|
-
|
|
20504
|
-
|
|
20505
|
-
|
|
20506
|
-
|
|
20507
|
-
|
|
20508
|
-
|
|
20509
|
-
|
|
20510
|
-
|
|
20511
|
-
|
|
20512
|
-
|
|
20513
|
-
|
|
20514
|
-
|
|
20897
|
+
const prevConditional = ctx.inConditional ?? 0;
|
|
20898
|
+
ctx.inConditional = prevConditional + 1;
|
|
20899
|
+
let cases;
|
|
20900
|
+
try {
|
|
20901
|
+
cases = node.cases.map((c) => {
|
|
20902
|
+
const stmts = ensureSwitchCaseBreak(
|
|
20903
|
+
lowerStructuredNodeForRegion(
|
|
20904
|
+
c.body,
|
|
20905
|
+
region,
|
|
20906
|
+
t4,
|
|
20907
|
+
ctx,
|
|
20908
|
+
declaredVars,
|
|
20909
|
+
regionCtx,
|
|
20910
|
+
skipInstructions
|
|
20911
|
+
),
|
|
20912
|
+
t4
|
|
20913
|
+
);
|
|
20914
|
+
if (stmts.length === 0) return null;
|
|
20915
|
+
return t4.switchCase(c.test ? lowerExpressionWithDeSSA(c.test, ctx) : null, stmts);
|
|
20916
|
+
}).filter((c) => !!c);
|
|
20917
|
+
} finally {
|
|
20918
|
+
ctx.inConditional = prevConditional;
|
|
20919
|
+
}
|
|
20515
20920
|
if (cases.length === 0) return [];
|
|
20516
20921
|
return [t4.switchStatement(lowerExpressionWithDeSSA(node.discriminant, ctx), cases)];
|
|
20517
20922
|
}
|
|
@@ -20964,6 +21369,7 @@ function collectExprDependencies(expr) {
|
|
|
20964
21369
|
if (p.kind === "SpreadElement") {
|
|
20965
21370
|
visit(p.argument);
|
|
20966
21371
|
} else {
|
|
21372
|
+
if (p.computed) visit(p.key);
|
|
20967
21373
|
visit(p.value);
|
|
20968
21374
|
}
|
|
20969
21375
|
});
|
|
@@ -21827,7 +22233,10 @@ function expressionContainsJSX(expr) {
|
|
|
21827
22233
|
case "ArrayExpression":
|
|
21828
22234
|
return expr.elements?.some((el) => expressionContainsJSX(el)) ?? false;
|
|
21829
22235
|
case "ObjectExpression":
|
|
21830
|
-
return expr.properties?.some((p) =>
|
|
22236
|
+
return expr.properties?.some((p) => {
|
|
22237
|
+
if (p.kind === "SpreadElement") return expressionContainsJSX(p.argument);
|
|
22238
|
+
return (p.computed ?? false) && expressionContainsJSX(p.key) || expressionContainsJSX(p.value);
|
|
22239
|
+
}) ?? false;
|
|
21831
22240
|
case "ConditionalExpression":
|
|
21832
22241
|
return expressionContainsJSX(expr.test) || expressionContainsJSX(expr.consequent) || expressionContainsJSX(expr.alternate);
|
|
21833
22242
|
case "ArrowFunction":
|
|
@@ -21941,7 +22350,7 @@ function expressionHasAwait(expr) {
|
|
|
21941
22350
|
return expr.elements.some((el) => el && expressionHasAwait(el));
|
|
21942
22351
|
case "ObjectExpression":
|
|
21943
22352
|
return expr.properties.some(
|
|
21944
|
-
(prop) => prop.kind === "Property" && expressionHasAwait(prop.value) || prop.kind === "SpreadElement" && expressionHasAwait(prop.argument)
|
|
22353
|
+
(prop) => prop.kind === "Property" && ((prop.computed ?? false) && expressionHasAwait(prop.key) || expressionHasAwait(prop.value)) || prop.kind === "SpreadElement" && expressionHasAwait(prop.argument)
|
|
21945
22354
|
);
|
|
21946
22355
|
case "TemplateLiteral":
|
|
21947
22356
|
return expr.expressions.some((ex) => expressionHasAwait(ex));
|
|
@@ -22012,6 +22421,7 @@ function collectCalledIdentifiers(fn) {
|
|
|
22012
22421
|
if (p.kind === "SpreadElement") {
|
|
22013
22422
|
visitExpr(p.argument);
|
|
22014
22423
|
} else {
|
|
22424
|
+
if (p.computed) visitExpr(p.key);
|
|
22015
22425
|
visitExpr(p.value);
|
|
22016
22426
|
}
|
|
22017
22427
|
});
|
|
@@ -22238,6 +22648,7 @@ function analyzeHookReturnInfo(fn, ctx) {
|
|
|
22238
22648
|
if (expr.kind === "ObjectExpression") {
|
|
22239
22649
|
expr.properties.forEach((prop) => {
|
|
22240
22650
|
if (prop.kind !== "Property") return;
|
|
22651
|
+
if (prop.computed) return;
|
|
22241
22652
|
const keyName = prop.key.kind === "Identifier" ? prop.key.name : prop.key.kind === "Literal" ? String(prop.key.value) : void 0;
|
|
22242
22653
|
if (!keyName) return;
|
|
22243
22654
|
if (prop.value.kind === "Identifier") {
|
|
@@ -22546,6 +22957,7 @@ function collectExpressionIdentifiers(expr, into) {
|
|
|
22546
22957
|
collectExpressionIdentifiers(prop.argument, into);
|
|
22547
22958
|
return;
|
|
22548
22959
|
}
|
|
22960
|
+
if (prop.computed) collectExpressionIdentifiers(prop.key, into);
|
|
22549
22961
|
collectExpressionIdentifiers(prop.value, into);
|
|
22550
22962
|
});
|
|
22551
22963
|
return;
|
|
@@ -22663,6 +23075,7 @@ function collectExpressionIdentifiersDeep(expr, into, bound = /* @__PURE__ */ ne
|
|
|
22663
23075
|
collectExpressionIdentifiersDeep(prop.argument, into, bound);
|
|
22664
23076
|
return;
|
|
22665
23077
|
}
|
|
23078
|
+
if (prop.computed) collectExpressionIdentifiersDeep(prop.key, into, bound);
|
|
22666
23079
|
collectExpressionIdentifiersDeep(prop.value, into, bound);
|
|
22667
23080
|
});
|
|
22668
23081
|
return;
|
|
@@ -24169,6 +24582,28 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
|
|
|
24169
24582
|
if (p.kind === "SpreadElement") {
|
|
24170
24583
|
return t4.spreadElement(lowerExpression(p.argument, ctx));
|
|
24171
24584
|
}
|
|
24585
|
+
const keyIsIdentifier = !p.computed && p.key.kind === "Identifier";
|
|
24586
|
+
const keyIdent = keyIsIdentifier ? p.key.name : "";
|
|
24587
|
+
const keyNode = p.computed ? lowerExpression(p.key, ctx) : keyIsIdentifier ? t4.identifier(keyIdent) : lowerExpression(p.key, ctx);
|
|
24588
|
+
if (p.propertyKind && p.propertyKind !== "init") {
|
|
24589
|
+
const valueExpr2 = lowerExpression(p.value, ctx);
|
|
24590
|
+
if (!t4.isFunctionExpression(valueExpr2)) {
|
|
24591
|
+
throw new HIRError(
|
|
24592
|
+
`Object method property did not lower to function expression.`,
|
|
24593
|
+
"CODEGEN_ERROR"
|
|
24594
|
+
);
|
|
24595
|
+
}
|
|
24596
|
+
const method = t4.objectMethod(
|
|
24597
|
+
p.propertyKind === "method" ? "method" : p.propertyKind,
|
|
24598
|
+
keyNode,
|
|
24599
|
+
valueExpr2.params,
|
|
24600
|
+
valueExpr2.body,
|
|
24601
|
+
!!p.computed
|
|
24602
|
+
);
|
|
24603
|
+
method.async = valueExpr2.async;
|
|
24604
|
+
method.generator = valueExpr2.generator;
|
|
24605
|
+
return method;
|
|
24606
|
+
}
|
|
24172
24607
|
const usesTracked = !!ctx.inPropsContext && (!ctx.nonReactiveScopeDepth || ctx.nonReactiveScopeDepth === 0) && p.value.kind !== "ArrowFunction" && p.value.kind !== "FunctionExpression" && expressionUsesTracked(p.value, ctx);
|
|
24173
24608
|
const valueExprRaw = usesTracked ? lowerTrackedExpression(p.value, ctx) : lowerExpression(p.value, ctx);
|
|
24174
24609
|
const shouldMemoProp = usesTracked && !t4.isIdentifier(valueExprRaw) && !t4.isMemberExpression(valueExprRaw) && !t4.isLiteral(valueExprRaw);
|
|
@@ -24184,13 +24619,11 @@ function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
|
|
|
24184
24619
|
t4.arrowFunctionExpression([], valueExprRaw)
|
|
24185
24620
|
]);
|
|
24186
24621
|
})() : valueExprRaw;
|
|
24187
|
-
const
|
|
24188
|
-
const keyNode = p.key.kind === "Identifier" ? t4.identifier(keyName) : t4.stringLiteral(keyName);
|
|
24189
|
-
const useShorthand = p.shorthand && t4.isIdentifier(valueExpr) && p.key.kind === "Identifier" && deSSAVarName(keyName) === valueExpr.name;
|
|
24622
|
+
const useShorthand = p.shorthand && t4.isIdentifier(valueExpr) && keyIsIdentifier && deSSAVarName(keyIdent) === valueExpr.name;
|
|
24190
24623
|
return t4.objectProperty(
|
|
24191
24624
|
useShorthand ? t4.identifier(valueExpr.name) : keyNode,
|
|
24192
24625
|
valueExpr,
|
|
24193
|
-
|
|
24626
|
+
!!p.computed,
|
|
24194
24627
|
useShorthand
|
|
24195
24628
|
);
|
|
24196
24629
|
})
|
|
@@ -24660,6 +25093,7 @@ function collectExpressionDependencies(expr, deps) {
|
|
|
24660
25093
|
if (p.kind === "SpreadElement") {
|
|
24661
25094
|
collectExpressionDependencies(p.argument, deps);
|
|
24662
25095
|
} else {
|
|
25096
|
+
if (p.computed) collectExpressionDependencies(p.key, deps);
|
|
24663
25097
|
collectExpressionDependencies(p.value, deps);
|
|
24664
25098
|
}
|
|
24665
25099
|
});
|
|
@@ -25184,6 +25618,7 @@ function countExpressionNodes(expr) {
|
|
|
25184
25618
|
case "ObjectExpression":
|
|
25185
25619
|
for (const prop of expr.properties) {
|
|
25186
25620
|
if (prop.kind === "Property") {
|
|
25621
|
+
if (prop.computed) count += countExpressionNodes(prop.key);
|
|
25187
25622
|
count += countExpressionNodes(prop.value);
|
|
25188
25623
|
} else if (prop.kind === "SpreadElement") {
|
|
25189
25624
|
count += countExpressionNodes(prop.argument);
|
|
@@ -26545,7 +26980,7 @@ function hirExpressionUsesIdentifiers(expr, names) {
|
|
|
26545
26980
|
if (prop.kind === "SpreadElement") {
|
|
26546
26981
|
return hirExpressionUsesIdentifiers(prop.argument, names);
|
|
26547
26982
|
}
|
|
26548
|
-
return hirExpressionUsesIdentifiers(prop.key, names) || hirExpressionUsesIdentifiers(prop.value, names);
|
|
26983
|
+
return (prop.computed ?? false) && hirExpressionUsesIdentifiers(prop.key, names) || hirExpressionUsesIdentifiers(prop.value, names);
|
|
26549
26984
|
});
|
|
26550
26985
|
case "TemplateLiteral":
|
|
26551
26986
|
return expr.expressions.some((e) => hirExpressionUsesIdentifiers(e, names));
|
|
@@ -27355,18 +27790,82 @@ function lowerTopLevelStatementBlock(statements, ctx, t4, name = "__module_segme
|
|
|
27355
27790
|
}
|
|
27356
27791
|
function transformControlFlowReturns(statements, ctx) {
|
|
27357
27792
|
const { t: t4 } = ctx;
|
|
27793
|
+
const reactiveAccessorNames = /* @__PURE__ */ new Set([
|
|
27794
|
+
...ctx.trackedVars,
|
|
27795
|
+
...ctx.signalVars ?? [],
|
|
27796
|
+
...ctx.memoVars ?? [],
|
|
27797
|
+
...ctx.aliasVars ?? [],
|
|
27798
|
+
...ctx.storeVars ?? []
|
|
27799
|
+
]);
|
|
27358
27800
|
const toStatements = (node) => t4.isBlockStatement(node) ? node.body : [node];
|
|
27359
27801
|
const endsWithReturn = (stmts) => {
|
|
27360
27802
|
if (stmts.length === 0) return false;
|
|
27361
27803
|
const tail = stmts[stmts.length - 1];
|
|
27362
27804
|
if (t4.isReturnStatement(tail)) return true;
|
|
27805
|
+
if (t4.isBlockStatement(tail)) {
|
|
27806
|
+
return endsWithReturn(tail.body);
|
|
27807
|
+
}
|
|
27363
27808
|
if (t4.isIfStatement(tail) && tail.consequent && tail.alternate) {
|
|
27364
27809
|
const conseqStmts = toStatements(tail.consequent);
|
|
27365
27810
|
const altStmts = toStatements(tail.alternate);
|
|
27366
27811
|
return endsWithReturn(conseqStmts) && endsWithReturn(altStmts);
|
|
27367
27812
|
}
|
|
27813
|
+
if (t4.isTryStatement(tail)) {
|
|
27814
|
+
if (tail.finalizer && endsWithReturn(tail.finalizer.body)) return true;
|
|
27815
|
+
if (!tail.handler) return false;
|
|
27816
|
+
return endsWithReturn(tail.block.body) && endsWithReturn(tail.handler.body.body);
|
|
27817
|
+
}
|
|
27368
27818
|
return false;
|
|
27369
27819
|
};
|
|
27820
|
+
function hasNodeMatch(nodes, predicate) {
|
|
27821
|
+
let found = false;
|
|
27822
|
+
const visit = (node) => {
|
|
27823
|
+
if (!node || found) return;
|
|
27824
|
+
if (predicate(node)) {
|
|
27825
|
+
found = true;
|
|
27826
|
+
return;
|
|
27827
|
+
}
|
|
27828
|
+
const keys = t4.VISITOR_KEYS;
|
|
27829
|
+
const visitorKeys = keys?.[node.type] ?? [];
|
|
27830
|
+
for (const key of visitorKeys) {
|
|
27831
|
+
const value = node[key];
|
|
27832
|
+
if (Array.isArray(value)) {
|
|
27833
|
+
for (const child of value) {
|
|
27834
|
+
if (child && typeof child === "object" && "type" in child) {
|
|
27835
|
+
visit(child);
|
|
27836
|
+
}
|
|
27837
|
+
if (found) return;
|
|
27838
|
+
}
|
|
27839
|
+
} else if (value && typeof value === "object" && "type" in value) {
|
|
27840
|
+
visit(value);
|
|
27841
|
+
}
|
|
27842
|
+
if (found) return;
|
|
27843
|
+
}
|
|
27844
|
+
};
|
|
27845
|
+
for (const node of nodes) {
|
|
27846
|
+
visit(node);
|
|
27847
|
+
if (found) return true;
|
|
27848
|
+
}
|
|
27849
|
+
return found;
|
|
27850
|
+
}
|
|
27851
|
+
const containsReturnStatement = (nodes) => hasNodeMatch(nodes, (node) => t4.isReturnStatement(node));
|
|
27852
|
+
const containsReactiveAccessorRead = (nodes) => hasNodeMatch(nodes, (node) => {
|
|
27853
|
+
if (!t4.isCallExpression(node) && !t4.isOptionalCallExpression(node)) return false;
|
|
27854
|
+
const callee = node.callee;
|
|
27855
|
+
return t4.isIdentifier(callee) && reactiveAccessorNames.has(callee.name);
|
|
27856
|
+
});
|
|
27857
|
+
const emitControlFlowFallbackWarning = (node, kind) => {
|
|
27858
|
+
const onWarn = ctx.options?.onWarn;
|
|
27859
|
+
if (!onWarn) return;
|
|
27860
|
+
const loc = node.loc?.start;
|
|
27861
|
+
onWarn({
|
|
27862
|
+
code: "FICT-R003" /* FICT_R003 */,
|
|
27863
|
+
message: `Reactive ${kind}-return lowering was skipped for this branch. The branch structure will not update reactively; refactor to a supported ${kind} form or use explicit runtime conditionals.`,
|
|
27864
|
+
fileName: ctx.options?.filename ?? "<unknown>",
|
|
27865
|
+
line: loc?.line ?? 0,
|
|
27866
|
+
column: loc ? loc.column + 1 : 0
|
|
27867
|
+
});
|
|
27868
|
+
};
|
|
27370
27869
|
function buildReturnBlock(stmts) {
|
|
27371
27870
|
if (stmts.length === 0) return null;
|
|
27372
27871
|
for (let i = 0; i < stmts.length; i++) {
|
|
@@ -27381,33 +27880,55 @@ function transformControlFlowReturns(statements, ctx) {
|
|
|
27381
27880
|
if (!endsWithReturn(stmts)) return null;
|
|
27382
27881
|
return stmts;
|
|
27383
27882
|
}
|
|
27384
|
-
function buildBranchFunction(stmts) {
|
|
27883
|
+
function buildBranchFunction(stmts, options) {
|
|
27385
27884
|
const block = buildReturnBlock(stmts);
|
|
27386
27885
|
if (!block) return null;
|
|
27886
|
+
if (options?.disallowRenderHooks && containsRenderOnlyHooks(block)) return null;
|
|
27387
27887
|
return t4.arrowFunctionExpression([], t4.blockStatement(block));
|
|
27388
27888
|
}
|
|
27389
|
-
function
|
|
27390
|
-
|
|
27391
|
-
|
|
27392
|
-
|
|
27393
|
-
|
|
27394
|
-
|
|
27395
|
-
|
|
27396
|
-
|
|
27397
|
-
|
|
27398
|
-
|
|
27399
|
-
|
|
27400
|
-
|
|
27889
|
+
function containsRenderOnlyHooks(nodes) {
|
|
27890
|
+
let found = false;
|
|
27891
|
+
const visit = (node) => {
|
|
27892
|
+
if (!node || found) return;
|
|
27893
|
+
if (t4.isCallExpression(node) || t4.isOptionalCallExpression(node)) {
|
|
27894
|
+
const callee = node.callee;
|
|
27895
|
+
if (t4.isIdentifier(callee) && callee.name.startsWith("__fictUse")) {
|
|
27896
|
+
if (callee.name !== "__fictUseEffect") {
|
|
27897
|
+
found = true;
|
|
27898
|
+
return;
|
|
27899
|
+
}
|
|
27900
|
+
}
|
|
27901
|
+
}
|
|
27902
|
+
const keys = t4.VISITOR_KEYS;
|
|
27903
|
+
const visitorKeys = keys?.[node.type] ?? [];
|
|
27904
|
+
for (const key of visitorKeys) {
|
|
27905
|
+
const value = node[key];
|
|
27906
|
+
if (Array.isArray(value)) {
|
|
27907
|
+
for (const child of value) {
|
|
27908
|
+
if (child && typeof child === "object" && "type" in child) {
|
|
27909
|
+
visit(child);
|
|
27910
|
+
}
|
|
27911
|
+
if (found) return;
|
|
27912
|
+
}
|
|
27913
|
+
} else if (value && typeof value === "object" && "type" in value) {
|
|
27914
|
+
visit(value);
|
|
27915
|
+
}
|
|
27916
|
+
if (found) return;
|
|
27917
|
+
}
|
|
27918
|
+
};
|
|
27919
|
+
for (const node of nodes) {
|
|
27920
|
+
visit(node);
|
|
27921
|
+
if (found) break;
|
|
27401
27922
|
}
|
|
27402
|
-
|
|
27403
|
-
|
|
27404
|
-
|
|
27923
|
+
return found;
|
|
27924
|
+
}
|
|
27925
|
+
function buildConditionalBindingExpr(testExpr, trueFn, falseFn) {
|
|
27405
27926
|
ctx.helpersUsed.add("conditional");
|
|
27406
27927
|
ctx.helpersUsed.add("createElement");
|
|
27407
27928
|
ctx.helpersUsed.add("onDestroy");
|
|
27408
27929
|
const bindingId = genTemp(ctx, "cond");
|
|
27409
27930
|
const args = [
|
|
27410
|
-
t4.arrowFunctionExpression([],
|
|
27931
|
+
t4.arrowFunctionExpression([], testExpr),
|
|
27411
27932
|
trueFn,
|
|
27412
27933
|
t4.identifier(RUNTIME_ALIASES.createElement),
|
|
27413
27934
|
falseFn
|
|
@@ -27429,15 +27950,210 @@ function transformControlFlowReturns(statements, ctx) {
|
|
|
27429
27950
|
[]
|
|
27430
27951
|
);
|
|
27431
27952
|
}
|
|
27432
|
-
|
|
27433
|
-
const
|
|
27953
|
+
function buildConditionalExpr(ifStmt, rest) {
|
|
27954
|
+
const consequentStmts = toStatements(ifStmt.consequent);
|
|
27955
|
+
if (!endsWithReturn(consequentStmts)) return null;
|
|
27956
|
+
let alternateStmts = null;
|
|
27957
|
+
if (ifStmt.alternate) {
|
|
27958
|
+
if (rest.length > 0) return null;
|
|
27959
|
+
alternateStmts = toStatements(ifStmt.alternate);
|
|
27960
|
+
if (!endsWithReturn(alternateStmts)) return null;
|
|
27961
|
+
} else {
|
|
27962
|
+
if (rest.length === 0) return null;
|
|
27963
|
+
alternateStmts = rest;
|
|
27964
|
+
if (!buildReturnBlock(alternateStmts)) return null;
|
|
27965
|
+
}
|
|
27966
|
+
const trueFn = buildBranchFunction(consequentStmts);
|
|
27967
|
+
const falseFn = alternateStmts ? buildBranchFunction(alternateStmts) : null;
|
|
27968
|
+
if (!trueFn || !falseFn) return null;
|
|
27969
|
+
return buildConditionalBindingExpr(ifStmt.test, trueFn, falseFn);
|
|
27970
|
+
}
|
|
27971
|
+
function isSupportedSwitchDiscriminant(_expr) {
|
|
27972
|
+
return true;
|
|
27973
|
+
}
|
|
27974
|
+
function buildSwitchConditionalExpr(switchStmt, rest) {
|
|
27975
|
+
const discriminant = switchStmt.discriminant;
|
|
27976
|
+
if (!isSupportedSwitchDiscriminant(discriminant)) return null;
|
|
27977
|
+
const trailingStatements = rest.length > 0 ? buildReturnBlock([...rest]) : [];
|
|
27978
|
+
if (rest.length > 0 && !trailingStatements) return null;
|
|
27979
|
+
const caseEntryCache = /* @__PURE__ */ new Map();
|
|
27980
|
+
const resolveCaseEntry = (startIndex) => {
|
|
27981
|
+
if (caseEntryCache.has(startIndex)) {
|
|
27982
|
+
return caseEntryCache.get(startIndex) ?? null;
|
|
27983
|
+
}
|
|
27984
|
+
const entry = [];
|
|
27985
|
+
for (let i = startIndex; i < switchStmt.cases.length; i++) {
|
|
27986
|
+
const currentCase = switchStmt.cases[i];
|
|
27987
|
+
const consequent = currentCase.consequent;
|
|
27988
|
+
for (let stmtIndex = 0; stmtIndex < consequent.length; stmtIndex++) {
|
|
27989
|
+
const stmt = consequent[stmtIndex];
|
|
27990
|
+
if (t4.isBreakStatement(stmt)) {
|
|
27991
|
+
if (stmt.label || stmtIndex !== consequent.length - 1) {
|
|
27992
|
+
caseEntryCache.set(startIndex, null);
|
|
27993
|
+
return null;
|
|
27994
|
+
}
|
|
27995
|
+
if (!trailingStatements || trailingStatements.length === 0) {
|
|
27996
|
+
caseEntryCache.set(startIndex, null);
|
|
27997
|
+
return null;
|
|
27998
|
+
}
|
|
27999
|
+
const withTrailing2 = [...entry, ...trailingStatements];
|
|
28000
|
+
caseEntryCache.set(startIndex, withTrailing2);
|
|
28001
|
+
return withTrailing2;
|
|
28002
|
+
}
|
|
28003
|
+
if (t4.isContinueStatement(stmt)) {
|
|
28004
|
+
caseEntryCache.set(startIndex, null);
|
|
28005
|
+
return null;
|
|
28006
|
+
}
|
|
28007
|
+
entry.push(stmt);
|
|
28008
|
+
}
|
|
28009
|
+
if (endsWithReturn(entry)) {
|
|
28010
|
+
caseEntryCache.set(startIndex, entry);
|
|
28011
|
+
return entry;
|
|
28012
|
+
}
|
|
28013
|
+
}
|
|
28014
|
+
if (!trailingStatements || trailingStatements.length === 0) {
|
|
28015
|
+
caseEntryCache.set(startIndex, null);
|
|
28016
|
+
return null;
|
|
28017
|
+
}
|
|
28018
|
+
const withTrailing = [...entry, ...trailingStatements];
|
|
28019
|
+
caseEntryCache.set(startIndex, withTrailing);
|
|
28020
|
+
return withTrailing;
|
|
28021
|
+
};
|
|
28022
|
+
const branches = [];
|
|
28023
|
+
let defaultStatements = null;
|
|
28024
|
+
for (let i = 0; i < switchStmt.cases.length; i++) {
|
|
28025
|
+
const caseNode = switchStmt.cases[i];
|
|
28026
|
+
const statements2 = resolveCaseEntry(i);
|
|
28027
|
+
if (!statements2) return null;
|
|
28028
|
+
if (caseNode.test) {
|
|
28029
|
+
branches.push({
|
|
28030
|
+
tests: [caseNode.test],
|
|
28031
|
+
statements: statements2
|
|
28032
|
+
});
|
|
28033
|
+
} else {
|
|
28034
|
+
defaultStatements = statements2;
|
|
28035
|
+
}
|
|
28036
|
+
}
|
|
28037
|
+
if (branches.length === 0 && !defaultStatements) return null;
|
|
28038
|
+
const fallbackStatements = defaultStatements ?? trailingStatements;
|
|
28039
|
+
if (!fallbackStatements || fallbackStatements.length === 0) return null;
|
|
28040
|
+
const fallbackFn = buildBranchFunction(fallbackStatements, { disallowRenderHooks: true });
|
|
28041
|
+
if (!fallbackFn) return null;
|
|
28042
|
+
ctx.helpersUsed.add("memo");
|
|
28043
|
+
const discriminantAccessor = genTemp(ctx, "switchDisc");
|
|
28044
|
+
const discriminantMemoDecl = t4.variableDeclaration("const", [
|
|
28045
|
+
t4.variableDeclarator(
|
|
28046
|
+
discriminantAccessor,
|
|
28047
|
+
t4.callExpression(t4.identifier(RUNTIME_ALIASES.memo), [
|
|
28048
|
+
t4.arrowFunctionExpression(
|
|
28049
|
+
[],
|
|
28050
|
+
t4.cloneNode(discriminant, true)
|
|
28051
|
+
)
|
|
28052
|
+
])
|
|
28053
|
+
)
|
|
28054
|
+
]);
|
|
28055
|
+
let currentExpr = t4.callExpression(
|
|
28056
|
+
t4.arrowFunctionExpression(
|
|
28057
|
+
[],
|
|
28058
|
+
t4.blockStatement(fallbackFn.body.body)
|
|
28059
|
+
),
|
|
28060
|
+
[]
|
|
28061
|
+
);
|
|
28062
|
+
for (let i = branches.length - 1; i >= 0; i--) {
|
|
28063
|
+
const branch = branches[i];
|
|
28064
|
+
const trueFn = buildBranchFunction(branch.statements, { disallowRenderHooks: true });
|
|
28065
|
+
if (!trueFn) return null;
|
|
28066
|
+
const falseFn = t4.arrowFunctionExpression(
|
|
28067
|
+
[],
|
|
28068
|
+
t4.blockStatement([t4.returnStatement(currentExpr)])
|
|
28069
|
+
);
|
|
28070
|
+
const comparisons = branch.tests.map(
|
|
28071
|
+
(test) => t4.binaryExpression(
|
|
28072
|
+
"===",
|
|
28073
|
+
t4.callExpression(t4.cloneNode(discriminantAccessor), []),
|
|
28074
|
+
t4.cloneNode(test, true)
|
|
28075
|
+
)
|
|
28076
|
+
);
|
|
28077
|
+
if (comparisons.length === 0) return null;
|
|
28078
|
+
const testExpr = comparisons.slice(1).reduce(
|
|
28079
|
+
(acc, expr) => t4.logicalExpression("||", acc, expr),
|
|
28080
|
+
comparisons[0]
|
|
28081
|
+
);
|
|
28082
|
+
currentExpr = buildConditionalBindingExpr(testExpr, trueFn, falseFn);
|
|
28083
|
+
}
|
|
28084
|
+
return t4.callExpression(
|
|
28085
|
+
t4.arrowFunctionExpression(
|
|
28086
|
+
[],
|
|
28087
|
+
t4.blockStatement([discriminantMemoDecl, t4.returnStatement(currentExpr)])
|
|
28088
|
+
),
|
|
28089
|
+
[]
|
|
28090
|
+
);
|
|
28091
|
+
}
|
|
28092
|
+
let nestedChanged = false;
|
|
28093
|
+
const rewrittenStatements = statements.map((stmt) => {
|
|
28094
|
+
if (!t4.isTryStatement(stmt)) return stmt;
|
|
28095
|
+
const transformedTryBlock = transformControlFlowReturns(stmt.block.body, ctx);
|
|
28096
|
+
const nextTryBlockBody = transformedTryBlock ?? stmt.block.body;
|
|
28097
|
+
let nextHandler = stmt.handler;
|
|
28098
|
+
if (stmt.handler) {
|
|
28099
|
+
const transformedCatchBlock = transformControlFlowReturns(stmt.handler.body.body, ctx);
|
|
28100
|
+
if (transformedCatchBlock) {
|
|
28101
|
+
nextHandler = t4.catchClause(
|
|
28102
|
+
stmt.handler.param ? t4.cloneNode(stmt.handler.param, true) : null,
|
|
28103
|
+
t4.blockStatement(transformedCatchBlock)
|
|
28104
|
+
);
|
|
28105
|
+
}
|
|
28106
|
+
}
|
|
28107
|
+
let nextFinalizer = stmt.finalizer;
|
|
28108
|
+
if (stmt.finalizer) {
|
|
28109
|
+
const transformedFinalizer = transformControlFlowReturns(stmt.finalizer.body, ctx);
|
|
28110
|
+
if (transformedFinalizer) {
|
|
28111
|
+
nextFinalizer = t4.blockStatement(transformedFinalizer);
|
|
28112
|
+
}
|
|
28113
|
+
}
|
|
28114
|
+
if (!transformedTryBlock && nextHandler === stmt.handler && nextFinalizer === stmt.finalizer) {
|
|
28115
|
+
return stmt;
|
|
28116
|
+
}
|
|
28117
|
+
nestedChanged = true;
|
|
28118
|
+
return t4.tryStatement(
|
|
28119
|
+
t4.blockStatement(nextTryBlockBody),
|
|
28120
|
+
nextHandler,
|
|
28121
|
+
nextFinalizer ? t4.cloneNode(nextFinalizer, true) : null
|
|
28122
|
+
);
|
|
28123
|
+
});
|
|
28124
|
+
for (let i = 0; i < rewrittenStatements.length; i++) {
|
|
28125
|
+
const stmt = rewrittenStatements[i];
|
|
27434
28126
|
if (!t4.isIfStatement(stmt)) continue;
|
|
27435
|
-
const
|
|
27436
|
-
|
|
27437
|
-
|
|
28127
|
+
const rest = rewrittenStatements.slice(i + 1);
|
|
28128
|
+
const conditionalExpr = buildConditionalExpr(stmt, rest);
|
|
28129
|
+
if (!conditionalExpr) {
|
|
28130
|
+
const hasReturn = containsReturnStatement([stmt, ...rest]);
|
|
28131
|
+
const hasReactiveReads = containsReactiveAccessorRead([stmt, ...rest]);
|
|
28132
|
+
if (hasReturn && hasReactiveReads) {
|
|
28133
|
+
emitControlFlowFallbackWarning(stmt, "if");
|
|
28134
|
+
}
|
|
28135
|
+
continue;
|
|
28136
|
+
}
|
|
28137
|
+
const prefix = rewrittenStatements.slice(0, i);
|
|
27438
28138
|
return [...prefix, t4.returnStatement(conditionalExpr)];
|
|
27439
28139
|
}
|
|
27440
|
-
|
|
28140
|
+
for (let i = 0; i < rewrittenStatements.length; i++) {
|
|
28141
|
+
const stmt = rewrittenStatements[i];
|
|
28142
|
+
if (!t4.isSwitchStatement(stmt)) continue;
|
|
28143
|
+
const rest = rewrittenStatements.slice(i + 1);
|
|
28144
|
+
const conditionalExpr = buildSwitchConditionalExpr(stmt, rest);
|
|
28145
|
+
if (!conditionalExpr) {
|
|
28146
|
+
const hasReturn = containsReturnStatement([stmt, ...rest]);
|
|
28147
|
+
const hasReactiveReads = containsReactiveAccessorRead([stmt, ...rest]);
|
|
28148
|
+
if (hasReturn && hasReactiveReads) {
|
|
28149
|
+
emitControlFlowFallbackWarning(stmt, "switch");
|
|
28150
|
+
}
|
|
28151
|
+
continue;
|
|
28152
|
+
}
|
|
28153
|
+
const prefix = rewrittenStatements.slice(0, i);
|
|
28154
|
+
return [...prefix, t4.returnStatement(conditionalExpr)];
|
|
28155
|
+
}
|
|
28156
|
+
return nestedChanged ? rewrittenStatements : null;
|
|
27441
28157
|
}
|
|
27442
28158
|
function lowerFunctionWithRegions(fn, ctx, options) {
|
|
27443
28159
|
const { t: t4 } = ctx;
|
|
@@ -28299,6 +29015,7 @@ function collectRootNodesFromExpression(expr, onBinding, onEffect) {
|
|
|
28299
29015
|
if (prop.kind === "SpreadElement") {
|
|
28300
29016
|
visit(prop.argument, shadowed);
|
|
28301
29017
|
} else {
|
|
29018
|
+
if (prop.computed) visit(prop.key, shadowed);
|
|
28302
29019
|
visit(prop.value, shadowed);
|
|
28303
29020
|
}
|
|
28304
29021
|
});
|
|
@@ -28443,6 +29160,14 @@ function collectDependenciesFromExpression(expr, deps, includeFunctionBodies, sh
|
|
|
28443
29160
|
shadowed
|
|
28444
29161
|
);
|
|
28445
29162
|
} else {
|
|
29163
|
+
if (prop.computed) {
|
|
29164
|
+
collectDependenciesFromExpression(
|
|
29165
|
+
prop.key,
|
|
29166
|
+
deps,
|
|
29167
|
+
includeFunctionBodies,
|
|
29168
|
+
shadowed
|
|
29169
|
+
);
|
|
29170
|
+
}
|
|
28446
29171
|
collectDependenciesFromExpression(
|
|
28447
29172
|
prop.value,
|
|
28448
29173
|
deps,
|
|
@@ -29405,7 +30130,7 @@ function expressionDependsOnReactive(expr, ctx) {
|
|
|
29405
30130
|
if (prop.kind === "SpreadElement") {
|
|
29406
30131
|
return expressionDependsOnReactive(prop.argument, ctx);
|
|
29407
30132
|
}
|
|
29408
|
-
return expressionDependsOnReactive(prop.value, ctx);
|
|
30133
|
+
return prop.computed && expressionDependsOnReactive(prop.key, ctx) || expressionDependsOnReactive(prop.value, ctx);
|
|
29409
30134
|
});
|
|
29410
30135
|
case "TemplateLiteral":
|
|
29411
30136
|
return expr.expressions.some((e) => expressionDependsOnReactive(e, ctx));
|
|
@@ -29505,6 +30230,7 @@ function collectWriteTargets(expr) {
|
|
|
29505
30230
|
if (prop.kind === "SpreadElement") {
|
|
29506
30231
|
visit(prop.argument);
|
|
29507
30232
|
} else {
|
|
30233
|
+
if (prop.computed) visit(prop.key);
|
|
29508
30234
|
visit(prop.value);
|
|
29509
30235
|
}
|
|
29510
30236
|
});
|
|
@@ -29578,6 +30304,7 @@ function collectMemberCallTargets(expr) {
|
|
|
29578
30304
|
if (prop.kind === "SpreadElement") {
|
|
29579
30305
|
visit(prop.argument);
|
|
29580
30306
|
} else {
|
|
30307
|
+
if (prop.computed) visit(prop.key);
|
|
29581
30308
|
visit(prop.value);
|
|
29582
30309
|
}
|
|
29583
30310
|
});
|
|
@@ -29705,7 +30432,7 @@ function expressionContainsImpureMarkers(expr) {
|
|
|
29705
30432
|
if (prop.kind === "SpreadElement") {
|
|
29706
30433
|
return expressionContainsImpureMarkers(prop.argument);
|
|
29707
30434
|
}
|
|
29708
|
-
return expressionContainsImpureMarkers(prop.value);
|
|
30435
|
+
return prop.computed && expressionContainsImpureMarkers(prop.key) || expressionContainsImpureMarkers(prop.value);
|
|
29709
30436
|
});
|
|
29710
30437
|
case "TemplateLiteral":
|
|
29711
30438
|
return expr.expressions.some((e) => expressionContainsImpureMarkers(e));
|
|
@@ -29910,6 +30637,7 @@ function extractConstObjectFields(expr, constants) {
|
|
|
29910
30637
|
const fields = /* @__PURE__ */ new Map();
|
|
29911
30638
|
for (const prop of expr.properties) {
|
|
29912
30639
|
if (prop.kind === "SpreadElement") return null;
|
|
30640
|
+
if (prop.computed) return null;
|
|
29913
30641
|
const key = getObjectLiteralKey(prop.key);
|
|
29914
30642
|
if (!key) return null;
|
|
29915
30643
|
const value = evaluateLiteral(prop.value, constants);
|
|
@@ -30037,6 +30765,7 @@ function replaceConstMemberExpressions(expr, constObjects, constArrays) {
|
|
|
30037
30765
|
}
|
|
30038
30766
|
return {
|
|
30039
30767
|
...prop,
|
|
30768
|
+
key: prop.computed ? replaceConstMemberExpressions(prop.key, constObjects, constArrays) : prop.key,
|
|
30040
30769
|
value: replaceConstMemberExpressions(
|
|
30041
30770
|
prop.value,
|
|
30042
30771
|
constObjects,
|
|
@@ -30287,6 +31016,7 @@ function simplifyChildren(expr, constants, options) {
|
|
|
30287
31016
|
if (prop.kind === "Property") {
|
|
30288
31017
|
return {
|
|
30289
31018
|
...prop,
|
|
31019
|
+
key: prop.computed ? simplifyAlgebraically(prop.key, constants, options) : prop.key,
|
|
30290
31020
|
value: simplifyAlgebraically(prop.value, constants, options)
|
|
30291
31021
|
};
|
|
30292
31022
|
}
|
|
@@ -30405,8 +31135,8 @@ function replaceIdentifiersWithConstants(expr, constants, context = {}) {
|
|
|
30405
31135
|
}
|
|
30406
31136
|
return {
|
|
30407
31137
|
...prop,
|
|
30408
|
-
|
|
30409
|
-
|
|
31138
|
+
key: prop.computed ? replaceIdentifiersWithConstants(prop.key, constants) : prop.key,
|
|
31139
|
+
value: replaceIdentifiersWithConstants(prop.value, constants)
|
|
30410
31140
|
};
|
|
30411
31141
|
})
|
|
30412
31142
|
};
|
|
@@ -30958,6 +31688,7 @@ function walkExpression(expr, add, ctx) {
|
|
|
30958
31688
|
if (prop.kind === "SpreadElement") {
|
|
30959
31689
|
walkExpression(prop.argument, add, ctx);
|
|
30960
31690
|
} else {
|
|
31691
|
+
if (prop.computed) walkExpression(prop.key, add, ctx);
|
|
30961
31692
|
walkExpression(prop.value, add, ctx);
|
|
30962
31693
|
}
|
|
30963
31694
|
});
|
|
@@ -31097,7 +31828,9 @@ function hashExpression(expr) {
|
|
|
31097
31828
|
return `arr:${expr.elements.map((el) => el ? hashExpression(el) : "null").join(",")}`;
|
|
31098
31829
|
case "ObjectExpression":
|
|
31099
31830
|
return `obj:${expr.properties.map(
|
|
31100
|
-
(p) => p.kind === "SpreadElement" ? `...${hashExpression(p.argument)}` : `${hashExpression(p.key)}:${hashExpression(
|
|
31831
|
+
(p) => p.kind === "SpreadElement" ? `...${hashExpression(p.argument)}` : `${p.computed ? "[]" : "."}${hashExpression(p.key)}:${hashExpression(
|
|
31832
|
+
p.value
|
|
31833
|
+
)}`
|
|
31101
31834
|
).join(",")}`;
|
|
31102
31835
|
case "TemplateLiteral":
|
|
31103
31836
|
return `tpl:${expr.quasis.join("|")}:${expr.expressions.map((e) => hashExpression(e)).join("|")}`;
|
|
@@ -31144,7 +31877,7 @@ function isPureExpression(expr, ctx) {
|
|
|
31144
31877
|
case "ObjectExpression":
|
|
31145
31878
|
return expr.properties.every((prop) => {
|
|
31146
31879
|
if (prop.kind === "SpreadElement") return isPureExpression(prop.argument, ctx);
|
|
31147
|
-
return isPureExpression(prop.value, ctx);
|
|
31880
|
+
return (!prop.computed || isPureExpression(prop.key, ctx)) && isPureExpression(prop.value, ctx);
|
|
31148
31881
|
});
|
|
31149
31882
|
case "MemberExpression":
|
|
31150
31883
|
case "OptionalMemberExpression":
|
|
@@ -31356,7 +32089,7 @@ function replaceIdentifier(expr, target, replacement, inFunctionBody) {
|
|
|
31356
32089
|
}
|
|
31357
32090
|
return {
|
|
31358
32091
|
...prop,
|
|
31359
|
-
key: prop.key,
|
|
32092
|
+
key: prop.computed ? replaceIdentifier(prop.key, target, replacement, inFunctionBody) : prop.key,
|
|
31360
32093
|
value: replaceIdentifier(prop.value, target, replacement, inFunctionBody)
|
|
31361
32094
|
};
|
|
31362
32095
|
})
|
|
@@ -31691,7 +32424,9 @@ function shouldSuppressWarning(suppressions, code, line) {
|
|
|
31691
32424
|
return entry.codes.has(code);
|
|
31692
32425
|
});
|
|
31693
32426
|
}
|
|
32427
|
+
var DEFAULT_ERROR_WARNING_CODES = /* @__PURE__ */ new Set(["FICT-R004"]);
|
|
31694
32428
|
function hasErrorEscalation(options) {
|
|
32429
|
+
if (DEFAULT_ERROR_WARNING_CODES.size > 0) return true;
|
|
31695
32430
|
if (options.warningsAsErrors === true) return true;
|
|
31696
32431
|
if (Array.isArray(options.warningsAsErrors) && options.warningsAsErrors.length > 0) return true;
|
|
31697
32432
|
if (options.warningLevels) {
|
|
@@ -31706,6 +32441,7 @@ function resolveWarningLevel(code, options) {
|
|
|
31706
32441
|
if (Array.isArray(options.warningsAsErrors) && options.warningsAsErrors.includes(code)) {
|
|
31707
32442
|
return "error";
|
|
31708
32443
|
}
|
|
32444
|
+
if (DEFAULT_ERROR_WARNING_CODES.has(code)) return "error";
|
|
31709
32445
|
return "warn";
|
|
31710
32446
|
}
|
|
31711
32447
|
function formatWarningAsError(warning) {
|
|
@@ -31819,18 +32555,66 @@ function isDynamicPropertyAccess(node, t4) {
|
|
|
31819
32555
|
if (!node.computed) return false;
|
|
31820
32556
|
return !(t4.isStringLiteral(node.property) || t4.isNumericLiteral(node.property));
|
|
31821
32557
|
}
|
|
31822
|
-
function runWarningPass(programPath,
|
|
31823
|
-
const
|
|
32558
|
+
function runWarningPass(programPath, stateBindingIds, stateRootBindingIds, reactiveBindingIds, effectMacroNames, warn, fileName, t4) {
|
|
32559
|
+
const hasTrackedBinding = (path2, name, tracked) => {
|
|
32560
|
+
const binding = path2.scope.getBinding(name);
|
|
32561
|
+
return !!(binding && tracked.has(binding.identifier));
|
|
32562
|
+
};
|
|
32563
|
+
const isStateRoot = (expr, path2) => {
|
|
32564
|
+
const root = getRootIdentifier(expr, t4);
|
|
32565
|
+
if (!root) return false;
|
|
32566
|
+
return hasTrackedBinding(path2, root.name, stateRootBindingIds);
|
|
32567
|
+
};
|
|
32568
|
+
const isReactiveRoot = (expr, path2) => {
|
|
31824
32569
|
const root = getRootIdentifier(expr, t4);
|
|
31825
|
-
|
|
32570
|
+
if (!root) return false;
|
|
32571
|
+
return hasTrackedBinding(path2, root.name, reactiveBindingIds);
|
|
32572
|
+
};
|
|
32573
|
+
const argumentHasReactive = (argPath) => {
|
|
32574
|
+
if (argPath.isSpreadElement()) {
|
|
32575
|
+
const inner = argPath.get("argument");
|
|
32576
|
+
return argumentHasReactive(inner);
|
|
32577
|
+
}
|
|
32578
|
+
if (argPath.isJSXElement() || argPath.isJSXFragment()) return false;
|
|
32579
|
+
if (argPath.isIdentifier()) {
|
|
32580
|
+
return hasTrackedBinding(argPath, argPath.node.name, reactiveBindingIds);
|
|
32581
|
+
}
|
|
32582
|
+
if (!argPath.isExpression()) return false;
|
|
32583
|
+
let found = false;
|
|
32584
|
+
argPath.traverse({
|
|
32585
|
+
Function(path2) {
|
|
32586
|
+
path2.skip();
|
|
32587
|
+
},
|
|
32588
|
+
JSXElement(path2) {
|
|
32589
|
+
path2.skip();
|
|
32590
|
+
},
|
|
32591
|
+
JSXFragment(path2) {
|
|
32592
|
+
path2.skip();
|
|
32593
|
+
},
|
|
32594
|
+
Identifier(idPath) {
|
|
32595
|
+
if (idPath.parentPath.isMemberExpression({ property: idPath.node }) && !idPath.parent.computed) {
|
|
32596
|
+
return;
|
|
32597
|
+
}
|
|
32598
|
+
if (idPath.parentPath.isObjectProperty({ key: idPath.node }) && !idPath.parent.computed && !idPath.parent.shorthand) {
|
|
32599
|
+
return;
|
|
32600
|
+
}
|
|
32601
|
+
const binding = idPath.scope.getBinding(idPath.node.name);
|
|
32602
|
+
if (binding && reactiveBindingIds.has(binding.identifier)) {
|
|
32603
|
+
found = true;
|
|
32604
|
+
idPath.stop();
|
|
32605
|
+
}
|
|
32606
|
+
}
|
|
32607
|
+
});
|
|
32608
|
+
return found;
|
|
31826
32609
|
};
|
|
31827
|
-
const reactiveNames = /* @__PURE__ */ new Set([...stateVars, ...derivedVars]);
|
|
31828
32610
|
programPath.traverse({
|
|
31829
32611
|
AssignmentExpression(path2) {
|
|
31830
32612
|
const { left } = path2.node;
|
|
31831
32613
|
if (t4.isIdentifier(left)) return;
|
|
31832
32614
|
if (t4.isMemberExpression(left) || t4.isOptionalMemberExpression(left)) {
|
|
31833
|
-
|
|
32615
|
+
const stateRoot = isStateRoot(left.object, path2);
|
|
32616
|
+
const reactiveRoot = isReactiveRoot(left.object, path2);
|
|
32617
|
+
if (stateRoot || reactiveRoot) {
|
|
31834
32618
|
emitWarning(
|
|
31835
32619
|
path2.node,
|
|
31836
32620
|
"FICT-M",
|
|
@@ -31847,13 +32631,16 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
31847
32631
|
fileName
|
|
31848
32632
|
);
|
|
31849
32633
|
}
|
|
32634
|
+
return;
|
|
31850
32635
|
}
|
|
31851
32636
|
}
|
|
31852
32637
|
},
|
|
31853
32638
|
UpdateExpression(path2) {
|
|
31854
32639
|
const arg = path2.node.argument;
|
|
31855
32640
|
if (t4.isMemberExpression(arg) || t4.isOptionalMemberExpression(arg)) {
|
|
31856
|
-
|
|
32641
|
+
const stateRoot = isStateRoot(arg.object, path2);
|
|
32642
|
+
const reactiveRoot = isReactiveRoot(arg.object, path2);
|
|
32643
|
+
if (stateRoot || reactiveRoot) {
|
|
31857
32644
|
emitWarning(
|
|
31858
32645
|
path2.node,
|
|
31859
32646
|
"FICT-M",
|
|
@@ -31870,6 +32657,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
31870
32657
|
fileName
|
|
31871
32658
|
);
|
|
31872
32659
|
}
|
|
32660
|
+
return;
|
|
31873
32661
|
}
|
|
31874
32662
|
}
|
|
31875
32663
|
},
|
|
@@ -31877,7 +32665,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
31877
32665
|
if (!path2.node.computed) return;
|
|
31878
32666
|
if (path2.parentPath.isAssignmentExpression({ left: path2.node })) return;
|
|
31879
32667
|
if (path2.parentPath.isUpdateExpression({ argument: path2.node })) return;
|
|
31880
|
-
if (isDynamicPropertyAccess(path2.node, t4) &&
|
|
32668
|
+
if (isDynamicPropertyAccess(path2.node, t4) && isReactiveRoot(path2.node.object, path2)) {
|
|
31881
32669
|
emitWarning(
|
|
31882
32670
|
path2.node,
|
|
31883
32671
|
"FICT-H",
|
|
@@ -31897,9 +32685,9 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
31897
32685
|
},
|
|
31898
32686
|
Identifier(idPath) {
|
|
31899
32687
|
const name = idPath.node.name;
|
|
31900
|
-
if (!reactiveNames.has(name)) return;
|
|
31901
32688
|
const binding = idPath.scope.getBinding(name);
|
|
31902
32689
|
if (!binding) return;
|
|
32690
|
+
if (!reactiveBindingIds.has(binding.identifier)) return;
|
|
31903
32691
|
if (binding.scope === idPath.scope || binding.scope === path2.scope) return;
|
|
31904
32692
|
captured.add(name);
|
|
31905
32693
|
}
|
|
@@ -31917,7 +32705,8 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
31917
32705
|
}
|
|
31918
32706
|
},
|
|
31919
32707
|
CallExpression(path2) {
|
|
31920
|
-
|
|
32708
|
+
const isEffect = isEffectCall(path2.node, t4, effectMacroNames);
|
|
32709
|
+
if (isEffect) {
|
|
31921
32710
|
const argPath = path2.get("arguments.0");
|
|
31922
32711
|
if (argPath?.isFunctionExpression() || argPath?.isArrowFunctionExpression()) {
|
|
31923
32712
|
let hasReactiveDependency = false;
|
|
@@ -31931,7 +32720,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
31931
32720
|
}
|
|
31932
32721
|
const binding = idPath.scope.getBinding(idPath.node.name);
|
|
31933
32722
|
if (binding && binding.scope === argPath.scope) return;
|
|
31934
|
-
if (
|
|
32723
|
+
if (binding && reactiveBindingIds.has(binding.identifier)) {
|
|
31935
32724
|
hasReactiveDependency = true;
|
|
31936
32725
|
idPath.stop();
|
|
31937
32726
|
}
|
|
@@ -31961,13 +32750,16 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
31961
32750
|
}
|
|
31962
32751
|
const isSafe = calleeName && SAFE_FUNCTIONS.has(calleeName);
|
|
31963
32752
|
if (isSafe) return;
|
|
31964
|
-
|
|
31965
|
-
|
|
31966
|
-
if (
|
|
32753
|
+
const argPaths = path2.get("arguments");
|
|
32754
|
+
for (const argPath of argPaths) {
|
|
32755
|
+
if (argPath.isIdentifier() && hasTrackedBinding(argPath, argPath.node.name, stateBindingIds)) {
|
|
32756
|
+
continue;
|
|
32757
|
+
}
|
|
32758
|
+
if (argumentHasReactive(argPath)) {
|
|
31967
32759
|
emitWarning(
|
|
31968
|
-
|
|
31969
|
-
"FICT-
|
|
31970
|
-
"
|
|
32760
|
+
argPath.node,
|
|
32761
|
+
"FICT-R002",
|
|
32762
|
+
"Reactive value escapes scope when passed to an unknown function; dependency tracking may be imprecise",
|
|
31971
32763
|
warn,
|
|
31972
32764
|
fileName
|
|
31973
32765
|
);
|
|
@@ -31979,7 +32771,7 @@ function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t4)
|
|
|
31979
32771
|
if (!path2.node.computed) return;
|
|
31980
32772
|
if (path2.parentPath.isAssignmentExpression({ left: path2.node })) return;
|
|
31981
32773
|
if (path2.parentPath.isUpdateExpression({ argument: path2.node })) return;
|
|
31982
|
-
if (isDynamicPropertyAccess(path2.node, t4) &&
|
|
32774
|
+
if (isDynamicPropertyAccess(path2.node, t4) && isReactiveRoot(path2.node.object, path2)) {
|
|
31983
32775
|
emitWarning(
|
|
31984
32776
|
path2.node,
|
|
31985
32777
|
"FICT-H",
|
|
@@ -32108,6 +32900,17 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
32108
32900
|
const name = getFunctionName(fnPath);
|
|
32109
32901
|
return name && isComponentName2(name) || isHookName2(name) || functionHasJSX(fnPath) || functionUsesStateLike(fnPath, t4);
|
|
32110
32902
|
};
|
|
32903
|
+
const isBoundDefinition = (fnPath) => fnPath.isFunctionDeclaration() || fnPath.parentPath.isVariableDeclarator() && fnPath.parentPath.node.init === fnPath.node;
|
|
32904
|
+
const isExportDefaultDefinition = (fnPath) => fnPath.parentPath?.isExportDefaultDeclaration() && fnPath.parentPath.node.declaration === fnPath.node;
|
|
32905
|
+
const isNamedComponentOrHookDefinition = (fnPath) => {
|
|
32906
|
+
if (!isBoundDefinition(fnPath)) return false;
|
|
32907
|
+
const name = getFunctionName(fnPath);
|
|
32908
|
+
return !!name && (isComponentName2(name) || isHookName2(name));
|
|
32909
|
+
};
|
|
32910
|
+
const isComponentDefinitionForProps = (fnPath) => {
|
|
32911
|
+
if (!isComponentDefinition(fnPath)) return false;
|
|
32912
|
+
return isBoundDefinition(fnPath) || isExportDefaultDefinition(fnPath);
|
|
32913
|
+
};
|
|
32111
32914
|
const memoHasSideEffects = (fn) => {
|
|
32112
32915
|
const pureCalls = new Set(
|
|
32113
32916
|
Array.from(SAFE_FUNCTIONS).filter(
|
|
@@ -32228,6 +33031,7 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
32228
33031
|
const stateMacroNames = /* @__PURE__ */ new Set(["$state"]);
|
|
32229
33032
|
const effectMacroNames = /* @__PURE__ */ new Set(["$effect"]);
|
|
32230
33033
|
const memoMacroNames = /* @__PURE__ */ new Set(["$memo", "createMemo"]);
|
|
33034
|
+
const importedReactiveBindingIds = /* @__PURE__ */ new Set();
|
|
32231
33035
|
path2.traverse({
|
|
32232
33036
|
ImportDeclaration(importPath) {
|
|
32233
33037
|
if (importPath.node.source.value !== "fict" && importPath.node.source.value !== "fict/slim")
|
|
@@ -32248,6 +33052,44 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
32248
33052
|
}
|
|
32249
33053
|
}
|
|
32250
33054
|
});
|
|
33055
|
+
path2.traverse({
|
|
33056
|
+
ImportDeclaration(importPath) {
|
|
33057
|
+
const meta = resolveModuleMetadata(
|
|
33058
|
+
importPath.node.source.value,
|
|
33059
|
+
fileName,
|
|
33060
|
+
optionsWithWarnings
|
|
33061
|
+
);
|
|
33062
|
+
if (!meta) return;
|
|
33063
|
+
const hasReactiveExports = Object.keys(meta.exports).length > 0;
|
|
33064
|
+
for (const spec of importPath.node.specifiers) {
|
|
33065
|
+
if (t4.isImportSpecifier(spec)) {
|
|
33066
|
+
const importedName = t4.isIdentifier(spec.imported) ? spec.imported.name : String(spec.imported.value);
|
|
33067
|
+
if (meta.exports[importedName]) {
|
|
33068
|
+
const binding = importPath.scope.getBinding(spec.local.name);
|
|
33069
|
+
if (binding) {
|
|
33070
|
+
importedReactiveBindingIds.add(binding.identifier);
|
|
33071
|
+
}
|
|
33072
|
+
}
|
|
33073
|
+
continue;
|
|
33074
|
+
}
|
|
33075
|
+
if (t4.isImportDefaultSpecifier(spec)) {
|
|
33076
|
+
if (meta.exports.default) {
|
|
33077
|
+
const binding = importPath.scope.getBinding(spec.local.name);
|
|
33078
|
+
if (binding) {
|
|
33079
|
+
importedReactiveBindingIds.add(binding.identifier);
|
|
33080
|
+
}
|
|
33081
|
+
}
|
|
33082
|
+
continue;
|
|
33083
|
+
}
|
|
33084
|
+
if (t4.isImportNamespaceSpecifier(spec) && hasReactiveExports) {
|
|
33085
|
+
const binding = importPath.scope.getBinding(spec.local.name);
|
|
33086
|
+
if (binding) {
|
|
33087
|
+
importedReactiveBindingIds.add(binding.identifier);
|
|
33088
|
+
}
|
|
33089
|
+
}
|
|
33090
|
+
}
|
|
33091
|
+
}
|
|
33092
|
+
});
|
|
32251
33093
|
path2.traverse({
|
|
32252
33094
|
JSXExpressionContainer(exprPath) {
|
|
32253
33095
|
const expr = exprPath.node.expression;
|
|
@@ -32258,10 +33100,10 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
32258
33100
|
const cb = expr.arguments[0];
|
|
32259
33101
|
if (!cb || !t4.isArrowFunctionExpression(cb) && !t4.isFunctionExpression(cb)) return;
|
|
32260
33102
|
const getReturnedJsx = (fn) => {
|
|
32261
|
-
if (t4.isJSXElement(fn.body)) return fn.body;
|
|
33103
|
+
if (t4.isJSXElement(fn.body) || t4.isJSXFragment(fn.body)) return fn.body;
|
|
32262
33104
|
if (t4.isBlockStatement(fn.body)) {
|
|
32263
33105
|
const ret = fn.body.body.find((stmt) => t4.isReturnStatement(stmt));
|
|
32264
|
-
if (ret && t4.isReturnStatement(ret) && ret.argument && t4.isJSXElement(ret.argument)) {
|
|
33106
|
+
if (ret && t4.isReturnStatement(ret) && ret.argument && (t4.isJSXElement(ret.argument) || t4.isJSXFragment(ret.argument))) {
|
|
32265
33107
|
return ret.argument;
|
|
32266
33108
|
}
|
|
32267
33109
|
}
|
|
@@ -32269,6 +33111,16 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
32269
33111
|
};
|
|
32270
33112
|
const jsx = getReturnedJsx(cb);
|
|
32271
33113
|
if (!jsx) return;
|
|
33114
|
+
if (t4.isJSXFragment(jsx)) {
|
|
33115
|
+
warn({
|
|
33116
|
+
code: "FICT-J002",
|
|
33117
|
+
message: "Missing key prop in list rendering.",
|
|
33118
|
+
fileName,
|
|
33119
|
+
line: expr.loc?.start.line ?? 0,
|
|
33120
|
+
column: expr.loc ? expr.loc.start.column + 1 : 0
|
|
33121
|
+
});
|
|
33122
|
+
return;
|
|
33123
|
+
}
|
|
32272
33124
|
let hasKey = false;
|
|
32273
33125
|
let hasUnknownSpread = false;
|
|
32274
33126
|
for (const attr of jsx.openingElement.attributes) {
|
|
@@ -32291,8 +33143,48 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
32291
33143
|
}
|
|
32292
33144
|
});
|
|
32293
33145
|
const stateVars = /* @__PURE__ */ new Set();
|
|
32294
|
-
const
|
|
33146
|
+
const stateBindingIds = /* @__PURE__ */ new Set();
|
|
33147
|
+
const derivedBindingIds = /* @__PURE__ */ new Set();
|
|
32295
33148
|
const destructuredAliases = /* @__PURE__ */ new Set();
|
|
33149
|
+
const aliasBindingIds = /* @__PURE__ */ new Set();
|
|
33150
|
+
const stateAliasBindingIds = /* @__PURE__ */ new Set();
|
|
33151
|
+
const propsBindingIds = /* @__PURE__ */ new Set();
|
|
33152
|
+
const hasTrackedBinding = (path3, name, tracked) => {
|
|
33153
|
+
const binding = path3.scope.getBinding(name);
|
|
33154
|
+
return !!(binding && tracked.has(binding.identifier));
|
|
33155
|
+
};
|
|
33156
|
+
const trackBindingByName = (path3, name, tracked) => {
|
|
33157
|
+
const binding = path3.scope.getBinding(name);
|
|
33158
|
+
if (binding) tracked.add(binding.identifier);
|
|
33159
|
+
};
|
|
33160
|
+
const hasReactiveAliasSourceBinding = (path3, name) => hasTrackedBinding(path3, name, stateBindingIds) || hasTrackedBinding(path3, name, derivedBindingIds) || hasTrackedBinding(path3, name, aliasBindingIds) || hasTrackedBinding(path3, name, destructuredAliases) || hasTrackedBinding(path3, name, importedReactiveBindingIds);
|
|
33161
|
+
const hasStateRootBinding = (path3, name) => hasTrackedBinding(path3, name, stateBindingIds) || hasTrackedBinding(path3, name, stateAliasBindingIds);
|
|
33162
|
+
const unwrapIdentifier = (node) => {
|
|
33163
|
+
if (!node) return null;
|
|
33164
|
+
let current = node;
|
|
33165
|
+
while (true) {
|
|
33166
|
+
if (t4.isTSAsExpression(current)) {
|
|
33167
|
+
current = current.expression;
|
|
33168
|
+
continue;
|
|
33169
|
+
}
|
|
33170
|
+
if (t4.isTSNonNullExpression(current)) {
|
|
33171
|
+
current = current.expression;
|
|
33172
|
+
continue;
|
|
33173
|
+
}
|
|
33174
|
+
if (t4.isTypeCastExpression?.(current)) {
|
|
33175
|
+
current = current.expression;
|
|
33176
|
+
continue;
|
|
33177
|
+
}
|
|
33178
|
+
break;
|
|
33179
|
+
}
|
|
33180
|
+
return t4.isIdentifier(current) ? current : null;
|
|
33181
|
+
};
|
|
33182
|
+
const isStateRootIdentifier = (exprPath) => {
|
|
33183
|
+
if (!exprPath) return null;
|
|
33184
|
+
const id = unwrapIdentifier(exprPath.node);
|
|
33185
|
+
if (!id) return null;
|
|
33186
|
+
return hasStateRootBinding(exprPath, id.name) ? id : null;
|
|
33187
|
+
};
|
|
32296
33188
|
path2.traverse({
|
|
32297
33189
|
VariableDeclarator(varPath) {
|
|
32298
33190
|
const init = varPath.node.init;
|
|
@@ -32328,6 +33220,7 @@ For module-level shared state, use one of these alternatives:
|
|
|
32328
33220
|
);
|
|
32329
33221
|
}
|
|
32330
33222
|
stateVars.add(varPath.node.id.name);
|
|
33223
|
+
trackBindingByName(varPath, varPath.node.id.name, stateBindingIds);
|
|
32331
33224
|
if (isInsideLoop(varPath) || isInsideConditional(varPath)) {
|
|
32332
33225
|
throw varPath.buildCodeFrameError(
|
|
32333
33226
|
`$state() cannot be declared inside loops or conditionals.
|
|
@@ -32350,25 +33243,36 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
32350
33243
|
let dependsOnState = false;
|
|
32351
33244
|
varPath.get("init").traverse({
|
|
32352
33245
|
Identifier(idPath) {
|
|
32353
|
-
if (
|
|
33246
|
+
if (hasTrackedBinding(idPath, idPath.node.name, stateBindingIds)) {
|
|
32354
33247
|
dependsOnState = true;
|
|
32355
33248
|
idPath.stop();
|
|
32356
33249
|
}
|
|
32357
33250
|
}
|
|
32358
33251
|
});
|
|
32359
33252
|
if (dependsOnState) {
|
|
32360
|
-
|
|
33253
|
+
trackBindingByName(varPath, varPath.node.id.name, derivedBindingIds);
|
|
32361
33254
|
}
|
|
32362
33255
|
}
|
|
32363
|
-
} else if ((t4.isObjectPattern(varPath.node.id) || t4.isArrayPattern(varPath.node.id)) && t4.isIdentifier(init) && stateVars.has(init.name)) {
|
|
32364
|
-
collectPatternIdentifiers(varPath.node.id).forEach((id) => destructuredAliases.add(id));
|
|
32365
33256
|
}
|
|
32366
33257
|
},
|
|
32367
33258
|
Function(fnPath) {
|
|
33259
|
+
if (isComponentDefinitionForProps(fnPath)) {
|
|
33260
|
+
for (const param of fnPath.node.params) {
|
|
33261
|
+
if (t4.isIdentifier(param)) {
|
|
33262
|
+
trackBindingByName(fnPath, param.name, propsBindingIds);
|
|
33263
|
+
continue;
|
|
33264
|
+
}
|
|
33265
|
+
if (t4.isPatternLike(param)) {
|
|
33266
|
+
collectPatternIdentifiers(param).forEach(
|
|
33267
|
+
(name) => trackBindingByName(fnPath, name, propsBindingIds)
|
|
33268
|
+
);
|
|
33269
|
+
}
|
|
33270
|
+
}
|
|
33271
|
+
}
|
|
32368
33272
|
const parentFn = fnPath.getFunctionParent();
|
|
32369
33273
|
if (!parentFn) return;
|
|
32370
33274
|
if (!isComponentLike(parentFn)) return;
|
|
32371
|
-
if (!
|
|
33275
|
+
if (!isNamedComponentOrHookDefinition(fnPath)) return;
|
|
32372
33276
|
emitWarning(
|
|
32373
33277
|
fnPath.node,
|
|
32374
33278
|
"FICT-C003",
|
|
@@ -32463,7 +33367,7 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
32463
33367
|
emitWarning(
|
|
32464
33368
|
callPath.node,
|
|
32465
33369
|
"FICT-R004",
|
|
32466
|
-
"Reactive creation inside non-JSX control flow
|
|
33370
|
+
"Reactive creation inside non-JSX control flow may not auto-dispose in complex paths. Prefer createScope/runInScope (or JSX-managed regions) for explicit lifecycle control.",
|
|
32467
33371
|
warn,
|
|
32468
33372
|
fileName
|
|
32469
33373
|
);
|
|
@@ -32497,7 +33401,7 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
32497
33401
|
"createEffect"
|
|
32498
33402
|
]);
|
|
32499
33403
|
callPath.node.arguments.forEach((arg) => {
|
|
32500
|
-
if (t4.isIdentifier(arg) &&
|
|
33404
|
+
if (t4.isIdentifier(arg) && hasTrackedBinding(callPath, arg.name, stateBindingIds) && (!calleeId || !allowedStateCallees.has(calleeId))) {
|
|
32501
33405
|
const loc = arg.loc?.start ?? callPath.node.loc?.start;
|
|
32502
33406
|
warn({
|
|
32503
33407
|
code: "FICT-S002",
|
|
@@ -32525,15 +33429,42 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
32525
33429
|
});
|
|
32526
33430
|
const aliasStack = [/* @__PURE__ */ new Set()];
|
|
32527
33431
|
const currentAliasSet = () => aliasStack[aliasStack.length - 1];
|
|
32528
|
-
const
|
|
33432
|
+
const getBindingIdentifier = (path3, name) => {
|
|
33433
|
+
const binding = path3.scope.getBinding(name);
|
|
33434
|
+
return binding ? binding.identifier : null;
|
|
33435
|
+
};
|
|
33436
|
+
const addAliasBinding = (path3, name) => {
|
|
33437
|
+
const aliasSet = currentAliasSet();
|
|
33438
|
+
if (!aliasSet) return;
|
|
33439
|
+
const bindingId = getBindingIdentifier(path3, name);
|
|
33440
|
+
if (!bindingId) return;
|
|
33441
|
+
aliasSet.add(bindingId);
|
|
33442
|
+
aliasBindingIds.add(bindingId);
|
|
33443
|
+
};
|
|
33444
|
+
const addStateAliasBinding = (path3, name) => {
|
|
33445
|
+
const bindingId = getBindingIdentifier(path3, name);
|
|
33446
|
+
if (!bindingId) return;
|
|
33447
|
+
stateAliasBindingIds.add(bindingId);
|
|
33448
|
+
};
|
|
33449
|
+
const isAliasBinding = (path3, name) => {
|
|
33450
|
+
const aliasSet = currentAliasSet();
|
|
33451
|
+
if (!aliasSet) return false;
|
|
33452
|
+
const bindingId = getBindingIdentifier(path3, name);
|
|
33453
|
+
return !!(bindingId && aliasSet.has(bindingId));
|
|
33454
|
+
};
|
|
33455
|
+
const isDestructuredAliasBinding = (path3, name) => {
|
|
33456
|
+
const bindingId = getBindingIdentifier(path3, name);
|
|
33457
|
+
return !!(bindingId && destructuredAliases.has(bindingId));
|
|
33458
|
+
};
|
|
33459
|
+
const rhsUsesReactive = (exprPath) => {
|
|
32529
33460
|
if (!exprPath) return false;
|
|
32530
|
-
if (exprPath.isIdentifier() && t4.isIdentifier(exprPath.node) &&
|
|
33461
|
+
if (exprPath.isIdentifier() && t4.isIdentifier(exprPath.node) && hasReactiveAliasSourceBinding(exprPath, exprPath.node.name)) {
|
|
32531
33462
|
return true;
|
|
32532
33463
|
}
|
|
32533
33464
|
let usesState = false;
|
|
32534
33465
|
exprPath.traverse({
|
|
32535
33466
|
Identifier(idPath) {
|
|
32536
|
-
if (
|
|
33467
|
+
if (hasReactiveAliasSourceBinding(idPath, idPath.node.name)) {
|
|
32537
33468
|
usesState = true;
|
|
32538
33469
|
idPath.stop();
|
|
32539
33470
|
}
|
|
@@ -32552,26 +33483,47 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
32552
33483
|
}
|
|
32553
33484
|
},
|
|
32554
33485
|
VariableDeclarator(varPath) {
|
|
32555
|
-
const
|
|
32556
|
-
|
|
33486
|
+
const initPath = varPath.get("init");
|
|
33487
|
+
const stateRootId = isStateRootIdentifier(initPath);
|
|
33488
|
+
if (t4.isIdentifier(varPath.node.id) && rhsUsesReactive(initPath)) {
|
|
32557
33489
|
debugLog("alias", "add from decl", varPath.node.id.name);
|
|
32558
|
-
|
|
33490
|
+
addAliasBinding(varPath, varPath.node.id.name);
|
|
33491
|
+
}
|
|
33492
|
+
if (t4.isIdentifier(varPath.node.id) && stateRootId) {
|
|
33493
|
+
addStateAliasBinding(varPath, varPath.node.id.name);
|
|
33494
|
+
}
|
|
33495
|
+
if (t4.isObjectPattern(varPath.node.id) || t4.isArrayPattern(varPath.node.id)) {
|
|
33496
|
+
if (rhsUsesReactive(initPath)) {
|
|
33497
|
+
const targets = collectPatternIdentifiers(varPath.node.id);
|
|
33498
|
+
for (const target of targets) {
|
|
33499
|
+
debugLog("alias", "add from destructuring decl", target);
|
|
33500
|
+
addAliasBinding(varPath, target);
|
|
33501
|
+
}
|
|
33502
|
+
}
|
|
33503
|
+
if (stateRootId) {
|
|
33504
|
+
collectPatternIdentifiers(varPath.node.id).forEach(
|
|
33505
|
+
(id) => trackBindingByName(varPath, id, destructuredAliases)
|
|
33506
|
+
);
|
|
33507
|
+
}
|
|
32559
33508
|
}
|
|
32560
33509
|
},
|
|
32561
33510
|
AssignmentExpression(assignPath) {
|
|
32562
|
-
const aliasSet = currentAliasSet();
|
|
32563
|
-
if (!aliasSet) return;
|
|
32564
33511
|
const rightPath = assignPath.get("right");
|
|
32565
|
-
const usesState =
|
|
33512
|
+
const usesState = rhsUsesReactive(rightPath);
|
|
33513
|
+
const stateRootId = isStateRootIdentifier(rightPath);
|
|
32566
33514
|
const left = assignPath.node.left;
|
|
32567
33515
|
if (t4.isIdentifier(left)) {
|
|
32568
33516
|
const targetName = left.name;
|
|
32569
33517
|
if (usesState) {
|
|
32570
33518
|
debugLog("alias", "add from assign", targetName);
|
|
32571
|
-
|
|
33519
|
+
addAliasBinding(assignPath, targetName);
|
|
33520
|
+
if (stateRootId) {
|
|
33521
|
+
addStateAliasBinding(assignPath, targetName);
|
|
33522
|
+
}
|
|
32572
33523
|
return;
|
|
32573
33524
|
}
|
|
32574
|
-
if (
|
|
33525
|
+
if (isAliasBinding(assignPath, targetName)) {
|
|
33526
|
+
if (isDestructuredAliasBinding(assignPath, targetName)) return;
|
|
32575
33527
|
debugLog("alias", "reassignment detected", targetName);
|
|
32576
33528
|
throw assignPath.buildCodeFrameError(
|
|
32577
33529
|
`Alias reassignment is not supported for "${targetName}"`
|
|
@@ -32585,11 +33537,18 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
32585
33537
|
if (usesState) {
|
|
32586
33538
|
for (const target of targets) {
|
|
32587
33539
|
debugLog("alias", "add from destructuring assign", target);
|
|
32588
|
-
|
|
33540
|
+
addAliasBinding(assignPath, target);
|
|
33541
|
+
}
|
|
33542
|
+
if (stateRootId) {
|
|
33543
|
+
targets.forEach(
|
|
33544
|
+
(target) => trackBindingByName(assignPath, target, destructuredAliases)
|
|
33545
|
+
);
|
|
32589
33546
|
}
|
|
32590
33547
|
return;
|
|
32591
33548
|
}
|
|
32592
|
-
const reassigned = targets.find(
|
|
33549
|
+
const reassigned = targets.find(
|
|
33550
|
+
(target) => isAliasBinding(assignPath, target) && !isDestructuredAliasBinding(assignPath, target)
|
|
33551
|
+
);
|
|
32593
33552
|
if (reassigned) {
|
|
32594
33553
|
debugLog("alias", "reassignment detected", reassigned);
|
|
32595
33554
|
throw assignPath.buildCodeFrameError(
|
|
@@ -32597,20 +33556,31 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
32597
33556
|
);
|
|
32598
33557
|
}
|
|
32599
33558
|
}
|
|
33559
|
+
},
|
|
33560
|
+
UpdateExpression(updatePath) {
|
|
33561
|
+
const arg = updatePath.node.argument;
|
|
33562
|
+
if (t4.isIdentifier(arg) && isAliasBinding(updatePath, arg.name) && !isDestructuredAliasBinding(updatePath, arg.name)) {
|
|
33563
|
+
debugLog("alias", "reassignment detected", arg.name);
|
|
33564
|
+
throw updatePath.buildCodeFrameError(
|
|
33565
|
+
`Alias reassignment is not supported for "${arg.name}"`
|
|
33566
|
+
);
|
|
33567
|
+
}
|
|
32600
33568
|
}
|
|
32601
33569
|
});
|
|
32602
|
-
if (
|
|
33570
|
+
if (derivedBindingIds.size > 0) {
|
|
32603
33571
|
path2.traverse({
|
|
32604
33572
|
AssignmentExpression(assignPath) {
|
|
32605
33573
|
const { left } = assignPath.node;
|
|
32606
|
-
if (t4.isIdentifier(left) &&
|
|
33574
|
+
if (t4.isIdentifier(left) && hasTrackedBinding(assignPath, left.name, derivedBindingIds)) {
|
|
32607
33575
|
throw assignPath.buildCodeFrameError(
|
|
32608
33576
|
`Cannot reassign derived value '${left.name}'. Derived values are read-only.`
|
|
32609
33577
|
);
|
|
32610
33578
|
}
|
|
32611
33579
|
if (t4.isObjectPattern(left) || t4.isArrayPattern(left)) {
|
|
32612
33580
|
const targets = collectPatternIdentifiers(left);
|
|
32613
|
-
const derivedTarget = targets.find(
|
|
33581
|
+
const derivedTarget = targets.find(
|
|
33582
|
+
(target) => hasTrackedBinding(assignPath, target, derivedBindingIds)
|
|
33583
|
+
);
|
|
32614
33584
|
if (derivedTarget) {
|
|
32615
33585
|
throw assignPath.buildCodeFrameError(
|
|
32616
33586
|
`Cannot reassign derived value '${derivedTarget}'. Derived values are read-only.`
|
|
@@ -32624,14 +33594,16 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
32624
33594
|
path2.traverse({
|
|
32625
33595
|
AssignmentExpression(assignPath) {
|
|
32626
33596
|
const { left } = assignPath.node;
|
|
32627
|
-
if (t4.isIdentifier(left) &&
|
|
33597
|
+
if (t4.isIdentifier(left) && hasTrackedBinding(assignPath, left.name, destructuredAliases)) {
|
|
32628
33598
|
throw assignPath.buildCodeFrameError(
|
|
32629
33599
|
`Cannot write to destructured state alias '${left.name}'. Update the original state (e.g. state.count++ or immutable update).`
|
|
32630
33600
|
);
|
|
32631
33601
|
}
|
|
32632
33602
|
if (t4.isObjectPattern(left) || t4.isArrayPattern(left)) {
|
|
32633
33603
|
const targets = collectPatternIdentifiers(left);
|
|
32634
|
-
const aliasTarget = targets.find(
|
|
33604
|
+
const aliasTarget = targets.find(
|
|
33605
|
+
(target) => hasTrackedBinding(assignPath, target, destructuredAliases)
|
|
33606
|
+
);
|
|
32635
33607
|
if (aliasTarget) {
|
|
32636
33608
|
throw assignPath.buildCodeFrameError(
|
|
32637
33609
|
`Cannot write to destructured state alias '${aliasTarget}'. Update the original state (e.g. state.count++ or immutable update).`
|
|
@@ -32641,7 +33613,7 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
32641
33613
|
},
|
|
32642
33614
|
UpdateExpression(updatePath) {
|
|
32643
33615
|
const arg = updatePath.node.argument;
|
|
32644
|
-
if (t4.isIdentifier(arg) &&
|
|
33616
|
+
if (t4.isIdentifier(arg) && hasTrackedBinding(updatePath, arg.name, destructuredAliases)) {
|
|
32645
33617
|
throw updatePath.buildCodeFrameError(
|
|
32646
33618
|
`Cannot write to destructured state alias '${arg.name}'. Update the original state (e.g. state.count++ or immutable update).`
|
|
32647
33619
|
);
|
|
@@ -32651,7 +33623,28 @@ or extract the nested logic into a custom hook (useXxx).`
|
|
|
32651
33623
|
}
|
|
32652
33624
|
const shouldRunWarnings = dev || hasErrorEscalation(options);
|
|
32653
33625
|
if (shouldRunWarnings) {
|
|
32654
|
-
|
|
33626
|
+
const stateRootBindingIds = /* @__PURE__ */ new Set([
|
|
33627
|
+
...stateBindingIds,
|
|
33628
|
+
...stateAliasBindingIds
|
|
33629
|
+
]);
|
|
33630
|
+
const reactiveBindingIds = /* @__PURE__ */ new Set([
|
|
33631
|
+
...stateBindingIds,
|
|
33632
|
+
...derivedBindingIds,
|
|
33633
|
+
...aliasBindingIds,
|
|
33634
|
+
...destructuredAliases,
|
|
33635
|
+
...propsBindingIds,
|
|
33636
|
+
...importedReactiveBindingIds
|
|
33637
|
+
]);
|
|
33638
|
+
runWarningPass(
|
|
33639
|
+
path2,
|
|
33640
|
+
stateBindingIds,
|
|
33641
|
+
stateRootBindingIds,
|
|
33642
|
+
reactiveBindingIds,
|
|
33643
|
+
effectMacroNames,
|
|
33644
|
+
warn,
|
|
33645
|
+
fileName,
|
|
33646
|
+
t4
|
|
33647
|
+
);
|
|
32655
33648
|
}
|
|
32656
33649
|
const fileAst = t4.file(path2.node);
|
|
32657
33650
|
const hir = buildHIR(
|