@fictjs/compiler 0.0.8 → 0.0.9
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 +413 -171
- package/dist/index.js +413 -171
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -14372,6 +14372,9 @@ function pathToString(path) {
|
|
|
14372
14372
|
|
|
14373
14373
|
// src/ir/build-hir.ts
|
|
14374
14374
|
var destructuringTempCounter = 0;
|
|
14375
|
+
var getLoc = (node) => {
|
|
14376
|
+
return node?.loc ?? null;
|
|
14377
|
+
};
|
|
14375
14378
|
function normalizeVarKind(kind) {
|
|
14376
14379
|
return kind === "const" || kind === "let" || kind === "var" ? kind : "let";
|
|
14377
14380
|
}
|
|
@@ -14441,7 +14444,8 @@ function buildHIR(ast) {
|
|
|
14441
14444
|
functions.push(
|
|
14442
14445
|
convertFunction(name, stmt.params, stmt.body.body, {
|
|
14443
14446
|
noMemo: programNoMemo,
|
|
14444
|
-
directives: stmt.body.directives
|
|
14447
|
+
directives: stmt.body.directives,
|
|
14448
|
+
loc: getLoc(stmt)
|
|
14445
14449
|
})
|
|
14446
14450
|
);
|
|
14447
14451
|
continue;
|
|
@@ -14454,7 +14458,8 @@ function buildHIR(ast) {
|
|
|
14454
14458
|
functions.push(
|
|
14455
14459
|
convertFunction(name, decl.params, decl.body.body, {
|
|
14456
14460
|
noMemo: programNoMemo,
|
|
14457
|
-
directives: decl.body.directives
|
|
14461
|
+
directives: decl.body.directives,
|
|
14462
|
+
loc: getLoc(decl)
|
|
14458
14463
|
})
|
|
14459
14464
|
);
|
|
14460
14465
|
postamble.push({ kind: "ExportFunction", name });
|
|
@@ -14472,9 +14477,11 @@ function buildHIR(ast) {
|
|
|
14472
14477
|
const hasExpressionBody = isArrow && !t.isBlockStatement(body);
|
|
14473
14478
|
const fnHIR = t.isBlockStatement(body) ? convertFunction(name, params, body.body, {
|
|
14474
14479
|
noMemo: programNoMemo,
|
|
14475
|
-
directives: body.directives
|
|
14480
|
+
directives: body.directives,
|
|
14481
|
+
loc: getLoc(v.init ?? v)
|
|
14476
14482
|
}) : convertFunction(name, params, [t.returnStatement(body)], {
|
|
14477
|
-
noMemo: programNoMemo
|
|
14483
|
+
noMemo: programNoMemo,
|
|
14484
|
+
loc: getLoc(v.init ?? v)
|
|
14478
14485
|
});
|
|
14479
14486
|
fnHIR.meta = { ...fnHIR.meta ?? {}, fromExpression: true, isArrow, hasExpressionBody };
|
|
14480
14487
|
functions.push(fnHIR);
|
|
@@ -14499,7 +14506,8 @@ function buildHIR(ast) {
|
|
|
14499
14506
|
functions.push(
|
|
14500
14507
|
convertFunction(name, decl.params, decl.body.body, {
|
|
14501
14508
|
noMemo: programNoMemo,
|
|
14502
|
-
directives: decl.body.directives
|
|
14509
|
+
directives: decl.body.directives,
|
|
14510
|
+
loc: getLoc(decl)
|
|
14503
14511
|
})
|
|
14504
14512
|
);
|
|
14505
14513
|
postamble.push({ kind: "ExportDefault", name });
|
|
@@ -14524,13 +14532,15 @@ function buildHIR(ast) {
|
|
|
14524
14532
|
const hasExpressionBody = isArrow && !t.isBlockStatement(body);
|
|
14525
14533
|
const fnHIR = t.isBlockStatement(body) ? convertFunction(name, params, body.body, {
|
|
14526
14534
|
noMemo: programNoMemo,
|
|
14527
|
-
directives: body.directives
|
|
14535
|
+
directives: body.directives,
|
|
14536
|
+
loc: getLoc(decl.init ?? decl)
|
|
14528
14537
|
}) : convertFunction(
|
|
14529
14538
|
name,
|
|
14530
14539
|
params,
|
|
14531
14540
|
[t.returnStatement(body)],
|
|
14532
14541
|
{
|
|
14533
|
-
noMemo: programNoMemo
|
|
14542
|
+
noMemo: programNoMemo,
|
|
14543
|
+
loc: getLoc(decl.init ?? decl)
|
|
14534
14544
|
}
|
|
14535
14545
|
);
|
|
14536
14546
|
fnHIR.meta = { ...fnHIR.meta ?? {}, fromExpression: true, isArrow, hasExpressionBody };
|
|
@@ -15038,11 +15048,12 @@ function convertFunction(name, params, body, options) {
|
|
|
15038
15048
|
name,
|
|
15039
15049
|
params: paramIds,
|
|
15040
15050
|
blocks,
|
|
15041
|
-
meta: hasNoMemo ? { noMemo: true } : void 0
|
|
15051
|
+
meta: hasNoMemo ? { noMemo: true } : void 0,
|
|
15052
|
+
loc: options?.loc ?? null
|
|
15042
15053
|
};
|
|
15043
15054
|
}
|
|
15044
15055
|
function convertStatementsToHIRFunction(name, statements) {
|
|
15045
|
-
return convertFunction(name, [], statements);
|
|
15056
|
+
return convertFunction(name, [], statements, { loc: getLoc(statements[0]) });
|
|
15046
15057
|
}
|
|
15047
15058
|
function convertAssignmentValue(expr) {
|
|
15048
15059
|
const right = convertExpression(expr.right);
|
|
@@ -15540,14 +15551,16 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15540
15551
|
return bb;
|
|
15541
15552
|
}
|
|
15542
15553
|
function convertExpression(node) {
|
|
15543
|
-
|
|
15554
|
+
const loc = getLoc(node);
|
|
15555
|
+
if (t.isIdentifier(node)) return { kind: "Identifier", name: node.name, loc };
|
|
15544
15556
|
if (t.isStringLiteral(node) || t.isNumericLiteral(node) || t.isBooleanLiteral(node) || t.isNullLiteral(node))
|
|
15545
|
-
return { kind: "Literal", value: node.value ?? null };
|
|
15557
|
+
return { kind: "Literal", value: node.value ?? null, loc };
|
|
15546
15558
|
if (t.isCallExpression(node)) {
|
|
15547
15559
|
const call = {
|
|
15548
15560
|
kind: "CallExpression",
|
|
15549
15561
|
callee: convertExpression(node.callee),
|
|
15550
|
-
arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean)
|
|
15562
|
+
arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
|
|
15563
|
+
loc
|
|
15551
15564
|
};
|
|
15552
15565
|
return call;
|
|
15553
15566
|
}
|
|
@@ -15562,7 +15575,8 @@ function convertExpression(node) {
|
|
|
15562
15575
|
object,
|
|
15563
15576
|
property,
|
|
15564
15577
|
computed: node.computed,
|
|
15565
|
-
optional: node.optional ?? true
|
|
15578
|
+
optional: node.optional ?? true,
|
|
15579
|
+
loc
|
|
15566
15580
|
};
|
|
15567
15581
|
return optionalMember;
|
|
15568
15582
|
}
|
|
@@ -15571,7 +15585,8 @@ function convertExpression(node) {
|
|
|
15571
15585
|
object,
|
|
15572
15586
|
property,
|
|
15573
15587
|
computed: node.computed,
|
|
15574
|
-
optional: false
|
|
15588
|
+
optional: false,
|
|
15589
|
+
loc
|
|
15575
15590
|
};
|
|
15576
15591
|
return member;
|
|
15577
15592
|
}
|
|
@@ -15580,7 +15595,8 @@ function convertExpression(node) {
|
|
|
15580
15595
|
kind: "BinaryExpression",
|
|
15581
15596
|
operator: node.operator,
|
|
15582
15597
|
left: convertExpression(node.left),
|
|
15583
|
-
right: convertExpression(node.right)
|
|
15598
|
+
right: convertExpression(node.right),
|
|
15599
|
+
loc
|
|
15584
15600
|
};
|
|
15585
15601
|
return bin;
|
|
15586
15602
|
}
|
|
@@ -15589,7 +15605,8 @@ function convertExpression(node) {
|
|
|
15589
15605
|
kind: "UnaryExpression",
|
|
15590
15606
|
operator: node.operator,
|
|
15591
15607
|
argument: convertExpression(node.argument),
|
|
15592
|
-
prefix: node.prefix
|
|
15608
|
+
prefix: node.prefix,
|
|
15609
|
+
loc
|
|
15593
15610
|
};
|
|
15594
15611
|
return un;
|
|
15595
15612
|
}
|
|
@@ -15598,7 +15615,8 @@ function convertExpression(node) {
|
|
|
15598
15615
|
kind: "LogicalExpression",
|
|
15599
15616
|
operator: node.operator,
|
|
15600
15617
|
left: convertExpression(node.left),
|
|
15601
|
-
right: convertExpression(node.right)
|
|
15618
|
+
right: convertExpression(node.right),
|
|
15619
|
+
loc
|
|
15602
15620
|
};
|
|
15603
15621
|
return log;
|
|
15604
15622
|
}
|
|
@@ -15607,7 +15625,8 @@ function convertExpression(node) {
|
|
|
15607
15625
|
kind: "ConditionalExpression",
|
|
15608
15626
|
test: convertExpression(node.test),
|
|
15609
15627
|
consequent: convertExpression(node.consequent),
|
|
15610
|
-
alternate: convertExpression(node.alternate)
|
|
15628
|
+
alternate: convertExpression(node.alternate),
|
|
15629
|
+
loc
|
|
15611
15630
|
};
|
|
15612
15631
|
return cond;
|
|
15613
15632
|
}
|
|
@@ -15619,12 +15638,14 @@ function convertExpression(node) {
|
|
|
15619
15638
|
if (t.isSpreadElement(el)) {
|
|
15620
15639
|
return {
|
|
15621
15640
|
kind: "SpreadElement",
|
|
15622
|
-
argument: convertExpression(el.argument)
|
|
15641
|
+
argument: convertExpression(el.argument),
|
|
15642
|
+
loc: getLoc(el)
|
|
15623
15643
|
};
|
|
15624
15644
|
}
|
|
15625
15645
|
if (t.isExpression(el)) return convertExpression(el);
|
|
15626
15646
|
return void 0;
|
|
15627
|
-
}).filter(Boolean)
|
|
15647
|
+
}).filter(Boolean),
|
|
15648
|
+
loc
|
|
15628
15649
|
};
|
|
15629
15650
|
return arr;
|
|
15630
15651
|
}
|
|
@@ -15635,7 +15656,8 @@ function convertExpression(node) {
|
|
|
15635
15656
|
if (t.isSpreadElement(prop)) {
|
|
15636
15657
|
return {
|
|
15637
15658
|
kind: "SpreadElement",
|
|
15638
|
-
argument: convertExpression(prop.argument)
|
|
15659
|
+
argument: convertExpression(prop.argument),
|
|
15660
|
+
loc: getLoc(prop)
|
|
15639
15661
|
};
|
|
15640
15662
|
}
|
|
15641
15663
|
if (t.isObjectMethod(prop)) {
|
|
@@ -15652,7 +15674,8 @@ function convertExpression(node) {
|
|
|
15652
15674
|
return {
|
|
15653
15675
|
kind: "Property",
|
|
15654
15676
|
key: keyExpr2,
|
|
15655
|
-
value: convertExpression(fnExpr)
|
|
15677
|
+
value: convertExpression(fnExpr),
|
|
15678
|
+
loc: getLoc(prop)
|
|
15656
15679
|
};
|
|
15657
15680
|
}
|
|
15658
15681
|
if (!t.isObjectProperty(prop) || prop.computed) return void 0;
|
|
@@ -15662,9 +15685,12 @@ function convertExpression(node) {
|
|
|
15662
15685
|
return {
|
|
15663
15686
|
kind: "Property",
|
|
15664
15687
|
key: keyExpr,
|
|
15665
|
-
value: convertExpression(prop.value)
|
|
15688
|
+
value: convertExpression(prop.value),
|
|
15689
|
+
shorthand: prop.shorthand && t.isIdentifier(prop.value),
|
|
15690
|
+
loc: getLoc(prop)
|
|
15666
15691
|
};
|
|
15667
|
-
}).filter(Boolean)
|
|
15692
|
+
}).filter(Boolean),
|
|
15693
|
+
loc
|
|
15668
15694
|
};
|
|
15669
15695
|
return obj;
|
|
15670
15696
|
}
|
|
@@ -15677,38 +15703,42 @@ function convertExpression(node) {
|
|
|
15677
15703
|
if (t.isJSXText(child)) {
|
|
15678
15704
|
const text = child.value;
|
|
15679
15705
|
if (text.trim()) {
|
|
15680
|
-
children.push({ kind: "text", value: text });
|
|
15706
|
+
children.push({ kind: "text", value: text, loc: getLoc(child) });
|
|
15681
15707
|
}
|
|
15682
15708
|
} else if (t.isJSXExpressionContainer(child)) {
|
|
15683
15709
|
if (!t.isJSXEmptyExpression(child.expression)) {
|
|
15684
15710
|
children.push({
|
|
15685
15711
|
kind: "expression",
|
|
15686
|
-
value: convertExpression(child.expression)
|
|
15712
|
+
value: convertExpression(child.expression),
|
|
15713
|
+
loc: getLoc(child)
|
|
15687
15714
|
});
|
|
15688
15715
|
}
|
|
15689
15716
|
} else if (t.isJSXElement(child)) {
|
|
15690
15717
|
children.push({
|
|
15691
15718
|
kind: "element",
|
|
15692
|
-
value: convertJSXElement(child)
|
|
15719
|
+
value: convertJSXElement(child),
|
|
15720
|
+
loc: getLoc(child)
|
|
15693
15721
|
});
|
|
15694
15722
|
} else if (t.isJSXFragment(child)) {
|
|
15695
15723
|
for (const fragChild of child.children) {
|
|
15696
15724
|
if (t.isJSXText(fragChild)) {
|
|
15697
15725
|
const text = fragChild.value;
|
|
15698
15726
|
if (text.trim()) {
|
|
15699
|
-
children.push({ kind: "text", value: text });
|
|
15727
|
+
children.push({ kind: "text", value: text, loc: getLoc(fragChild) });
|
|
15700
15728
|
}
|
|
15701
15729
|
} else if (t.isJSXExpressionContainer(fragChild)) {
|
|
15702
15730
|
if (!t.isJSXEmptyExpression(fragChild.expression)) {
|
|
15703
15731
|
children.push({
|
|
15704
15732
|
kind: "expression",
|
|
15705
|
-
value: convertExpression(fragChild.expression)
|
|
15733
|
+
value: convertExpression(fragChild.expression),
|
|
15734
|
+
loc: getLoc(fragChild)
|
|
15706
15735
|
});
|
|
15707
15736
|
}
|
|
15708
15737
|
} else if (t.isJSXElement(fragChild)) {
|
|
15709
15738
|
children.push({
|
|
15710
15739
|
kind: "element",
|
|
15711
|
-
value: convertJSXElement(fragChild)
|
|
15740
|
+
value: convertJSXElement(fragChild),
|
|
15741
|
+
loc: getLoc(fragChild)
|
|
15712
15742
|
});
|
|
15713
15743
|
}
|
|
15714
15744
|
}
|
|
@@ -15716,24 +15746,27 @@ function convertExpression(node) {
|
|
|
15716
15746
|
}
|
|
15717
15747
|
return {
|
|
15718
15748
|
kind: "JSXElement",
|
|
15719
|
-
tagName: { kind: "Identifier", name: "Fragment" },
|
|
15749
|
+
tagName: { kind: "Identifier", name: "Fragment", loc: getLoc(node) },
|
|
15720
15750
|
isComponent: true,
|
|
15721
15751
|
attributes: [],
|
|
15722
|
-
children
|
|
15752
|
+
children,
|
|
15753
|
+
loc: getLoc(node)
|
|
15723
15754
|
};
|
|
15724
15755
|
}
|
|
15725
15756
|
if (t.isArrowFunctionExpression(node)) {
|
|
15726
15757
|
if (t.isBlockStatement(node.body)) {
|
|
15727
15758
|
const nested = convertFunction(void 0, node.params, node.body.body, {
|
|
15728
15759
|
noMemo: hasNoMemoDirectiveInStatements(node.body.body),
|
|
15729
|
-
directives: node.body.directives
|
|
15760
|
+
directives: node.body.directives,
|
|
15761
|
+
loc: getLoc(node)
|
|
15730
15762
|
});
|
|
15731
15763
|
const arrow = {
|
|
15732
15764
|
kind: "ArrowFunction",
|
|
15733
15765
|
params: nested.params,
|
|
15734
15766
|
body: nested.blocks,
|
|
15735
15767
|
isExpression: false,
|
|
15736
|
-
isAsync: node.async
|
|
15768
|
+
isAsync: node.async,
|
|
15769
|
+
loc
|
|
15737
15770
|
};
|
|
15738
15771
|
return arrow;
|
|
15739
15772
|
} else {
|
|
@@ -15744,7 +15777,8 @@ function convertExpression(node) {
|
|
|
15744
15777
|
).flat(),
|
|
15745
15778
|
body: convertExpression(node.body),
|
|
15746
15779
|
isExpression: true,
|
|
15747
|
-
isAsync: node.async
|
|
15780
|
+
isAsync: node.async,
|
|
15781
|
+
loc
|
|
15748
15782
|
};
|
|
15749
15783
|
return arrow;
|
|
15750
15784
|
}
|
|
@@ -15752,14 +15786,16 @@ function convertExpression(node) {
|
|
|
15752
15786
|
if (t.isFunctionExpression(node)) {
|
|
15753
15787
|
const nested = convertFunction(void 0, node.params, node.body.body, {
|
|
15754
15788
|
noMemo: hasNoMemoDirectiveInStatements(node.body.body),
|
|
15755
|
-
directives: node.body.directives
|
|
15789
|
+
directives: node.body.directives,
|
|
15790
|
+
loc: getLoc(node)
|
|
15756
15791
|
});
|
|
15757
15792
|
const fn = {
|
|
15758
15793
|
kind: "FunctionExpression",
|
|
15759
15794
|
name: node.id?.name ?? "",
|
|
15760
15795
|
params: nested.params,
|
|
15761
15796
|
body: nested.blocks,
|
|
15762
|
-
isAsync: node.async
|
|
15797
|
+
isAsync: node.async,
|
|
15798
|
+
loc
|
|
15763
15799
|
};
|
|
15764
15800
|
return fn;
|
|
15765
15801
|
}
|
|
@@ -15768,7 +15804,8 @@ function convertExpression(node) {
|
|
|
15768
15804
|
kind: "AssignmentExpression",
|
|
15769
15805
|
operator: node.operator,
|
|
15770
15806
|
left: convertExpression(node.left),
|
|
15771
|
-
right: convertExpression(node.right)
|
|
15807
|
+
right: convertExpression(node.right),
|
|
15808
|
+
loc
|
|
15772
15809
|
};
|
|
15773
15810
|
return assign;
|
|
15774
15811
|
}
|
|
@@ -15777,7 +15814,8 @@ function convertExpression(node) {
|
|
|
15777
15814
|
kind: "UpdateExpression",
|
|
15778
15815
|
operator: node.operator,
|
|
15779
15816
|
argument: convertExpression(node.argument),
|
|
15780
|
-
prefix: node.prefix
|
|
15817
|
+
prefix: node.prefix,
|
|
15818
|
+
loc
|
|
15781
15819
|
};
|
|
15782
15820
|
return update;
|
|
15783
15821
|
}
|
|
@@ -15785,34 +15823,39 @@ function convertExpression(node) {
|
|
|
15785
15823
|
const template = {
|
|
15786
15824
|
kind: "TemplateLiteral",
|
|
15787
15825
|
quasis: node.quasis.map((q) => q.value.cooked ?? q.value.raw),
|
|
15788
|
-
expressions: node.expressions.map((e) => convertExpression(e))
|
|
15826
|
+
expressions: node.expressions.map((e) => convertExpression(e)),
|
|
15827
|
+
loc
|
|
15789
15828
|
};
|
|
15790
15829
|
return template;
|
|
15791
15830
|
}
|
|
15792
15831
|
if (t.isAwaitExpression(node)) {
|
|
15793
15832
|
return {
|
|
15794
15833
|
kind: "AwaitExpression",
|
|
15795
|
-
argument: convertExpression(node.argument)
|
|
15834
|
+
argument: convertExpression(node.argument),
|
|
15835
|
+
loc
|
|
15796
15836
|
};
|
|
15797
15837
|
}
|
|
15798
15838
|
if (t.isNewExpression(node)) {
|
|
15799
15839
|
return {
|
|
15800
15840
|
kind: "NewExpression",
|
|
15801
15841
|
callee: convertExpression(node.callee),
|
|
15802
|
-
arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean)
|
|
15842
|
+
arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
|
|
15843
|
+
loc
|
|
15803
15844
|
};
|
|
15804
15845
|
}
|
|
15805
15846
|
if (t.isSequenceExpression(node)) {
|
|
15806
15847
|
return {
|
|
15807
15848
|
kind: "SequenceExpression",
|
|
15808
|
-
expressions: node.expressions.map((e) => convertExpression(e))
|
|
15849
|
+
expressions: node.expressions.map((e) => convertExpression(e)),
|
|
15850
|
+
loc
|
|
15809
15851
|
};
|
|
15810
15852
|
}
|
|
15811
15853
|
if (t.isYieldExpression(node)) {
|
|
15812
15854
|
return {
|
|
15813
15855
|
kind: "YieldExpression",
|
|
15814
15856
|
argument: node.argument ? convertExpression(node.argument) : null,
|
|
15815
|
-
delegate: node.delegate
|
|
15857
|
+
delegate: node.delegate,
|
|
15858
|
+
loc
|
|
15816
15859
|
};
|
|
15817
15860
|
}
|
|
15818
15861
|
if (t.isOptionalCallExpression(node)) {
|
|
@@ -15820,7 +15863,8 @@ function convertExpression(node) {
|
|
|
15820
15863
|
kind: "OptionalCallExpression",
|
|
15821
15864
|
callee: convertExpression(node.callee),
|
|
15822
15865
|
arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
|
|
15823
|
-
optional: node.optional
|
|
15866
|
+
optional: node.optional,
|
|
15867
|
+
loc
|
|
15824
15868
|
};
|
|
15825
15869
|
}
|
|
15826
15870
|
if (t.isTaggedTemplateExpression(node)) {
|
|
@@ -15832,8 +15876,10 @@ function convertExpression(node) {
|
|
|
15832
15876
|
quasis: node.quasi.quasis.map((q) => q.value.cooked ?? q.value.raw),
|
|
15833
15877
|
expressions: node.quasi.expressions.map(
|
|
15834
15878
|
(e) => convertExpression(e)
|
|
15835
|
-
)
|
|
15836
|
-
|
|
15879
|
+
),
|
|
15880
|
+
loc: getLoc(node.quasi)
|
|
15881
|
+
},
|
|
15882
|
+
loc
|
|
15837
15883
|
};
|
|
15838
15884
|
}
|
|
15839
15885
|
if (t.isClassExpression(node)) {
|
|
@@ -15841,17 +15887,18 @@ function convertExpression(node) {
|
|
|
15841
15887
|
kind: "ClassExpression",
|
|
15842
15888
|
name: node.id?.name,
|
|
15843
15889
|
superClass: node.superClass ? convertExpression(node.superClass) : void 0,
|
|
15844
|
-
body: node.body.body
|
|
15890
|
+
body: node.body.body,
|
|
15845
15891
|
// Store as Babel AST for now
|
|
15892
|
+
loc
|
|
15846
15893
|
};
|
|
15847
15894
|
}
|
|
15848
15895
|
if (t.isThisExpression(node)) {
|
|
15849
|
-
return { kind: "ThisExpression" };
|
|
15896
|
+
return { kind: "ThisExpression", loc };
|
|
15850
15897
|
}
|
|
15851
15898
|
if (t.isSuper(node)) {
|
|
15852
|
-
return { kind: "SuperExpression" };
|
|
15899
|
+
return { kind: "SuperExpression", loc };
|
|
15853
15900
|
}
|
|
15854
|
-
const fallback = { kind: "Literal", value: void 0 };
|
|
15901
|
+
const fallback = { kind: "Literal", value: void 0, loc };
|
|
15855
15902
|
return fallback;
|
|
15856
15903
|
}
|
|
15857
15904
|
function convertJSXElement(node) {
|
|
@@ -15862,7 +15909,7 @@ function convertJSXElement(node) {
|
|
|
15862
15909
|
const name = opening.name.name;
|
|
15863
15910
|
const firstChar = name[0];
|
|
15864
15911
|
if (firstChar && firstChar === firstChar.toUpperCase()) {
|
|
15865
|
-
tagName = { kind: "Identifier", name };
|
|
15912
|
+
tagName = { kind: "Identifier", name, loc: getLoc(opening.name) };
|
|
15866
15913
|
isComponent = true;
|
|
15867
15914
|
} else {
|
|
15868
15915
|
tagName = name;
|
|
@@ -15880,20 +15927,22 @@ function convertJSXElement(node) {
|
|
|
15880
15927
|
name: "",
|
|
15881
15928
|
value: null,
|
|
15882
15929
|
isSpread: true,
|
|
15883
|
-
spreadExpr: convertExpression(attr.argument)
|
|
15930
|
+
spreadExpr: convertExpression(attr.argument),
|
|
15931
|
+
loc: getLoc(attr)
|
|
15884
15932
|
});
|
|
15885
15933
|
} else if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
|
|
15886
15934
|
let value = null;
|
|
15887
15935
|
if (attr.value) {
|
|
15888
15936
|
if (t.isStringLiteral(attr.value)) {
|
|
15889
|
-
value = { kind: "Literal", value: attr.value.value };
|
|
15937
|
+
value = { kind: "Literal", value: attr.value.value, loc: getLoc(attr.value) };
|
|
15890
15938
|
} else if (t.isJSXExpressionContainer(attr.value) && !t.isJSXEmptyExpression(attr.value.expression)) {
|
|
15891
15939
|
value = convertExpression(attr.value.expression);
|
|
15892
15940
|
}
|
|
15893
15941
|
}
|
|
15894
15942
|
attributes.push({
|
|
15895
15943
|
name: attr.name.name,
|
|
15896
|
-
value
|
|
15944
|
+
value,
|
|
15945
|
+
loc: getLoc(attr)
|
|
15897
15946
|
});
|
|
15898
15947
|
}
|
|
15899
15948
|
}
|
|
@@ -15902,38 +15951,42 @@ function convertJSXElement(node) {
|
|
|
15902
15951
|
if (t.isJSXText(child)) {
|
|
15903
15952
|
const text = child.value;
|
|
15904
15953
|
if (text.trim()) {
|
|
15905
|
-
children.push({ kind: "text", value: text });
|
|
15954
|
+
children.push({ kind: "text", value: text, loc: getLoc(child) });
|
|
15906
15955
|
}
|
|
15907
15956
|
} else if (t.isJSXExpressionContainer(child)) {
|
|
15908
15957
|
if (!t.isJSXEmptyExpression(child.expression)) {
|
|
15909
15958
|
children.push({
|
|
15910
15959
|
kind: "expression",
|
|
15911
|
-
value: convertExpression(child.expression)
|
|
15960
|
+
value: convertExpression(child.expression),
|
|
15961
|
+
loc: getLoc(child)
|
|
15912
15962
|
});
|
|
15913
15963
|
}
|
|
15914
15964
|
} else if (t.isJSXElement(child)) {
|
|
15915
15965
|
children.push({
|
|
15916
15966
|
kind: "element",
|
|
15917
|
-
value: convertJSXElement(child)
|
|
15967
|
+
value: convertJSXElement(child),
|
|
15968
|
+
loc: getLoc(child)
|
|
15918
15969
|
});
|
|
15919
15970
|
} else if (t.isJSXFragment(child)) {
|
|
15920
15971
|
for (const fragChild of child.children) {
|
|
15921
15972
|
if (t.isJSXText(fragChild)) {
|
|
15922
15973
|
const text = fragChild.value;
|
|
15923
15974
|
if (text.trim()) {
|
|
15924
|
-
children.push({ kind: "text", value: text });
|
|
15975
|
+
children.push({ kind: "text", value: text, loc: getLoc(fragChild) });
|
|
15925
15976
|
}
|
|
15926
15977
|
} else if (t.isJSXExpressionContainer(fragChild)) {
|
|
15927
15978
|
if (!t.isJSXEmptyExpression(fragChild.expression)) {
|
|
15928
15979
|
children.push({
|
|
15929
15980
|
kind: "expression",
|
|
15930
|
-
value: convertExpression(fragChild.expression)
|
|
15981
|
+
value: convertExpression(fragChild.expression),
|
|
15982
|
+
loc: getLoc(fragChild)
|
|
15931
15983
|
});
|
|
15932
15984
|
}
|
|
15933
15985
|
} else if (t.isJSXElement(fragChild)) {
|
|
15934
15986
|
children.push({
|
|
15935
15987
|
kind: "element",
|
|
15936
|
-
value: convertJSXElement(fragChild)
|
|
15988
|
+
value: convertJSXElement(fragChild),
|
|
15989
|
+
loc: getLoc(fragChild)
|
|
15937
15990
|
});
|
|
15938
15991
|
}
|
|
15939
15992
|
}
|
|
@@ -15944,21 +15997,27 @@ function convertJSXElement(node) {
|
|
|
15944
15997
|
tagName,
|
|
15945
15998
|
isComponent,
|
|
15946
15999
|
attributes,
|
|
15947
|
-
children
|
|
16000
|
+
children,
|
|
16001
|
+
loc: getLoc(node)
|
|
15948
16002
|
};
|
|
15949
16003
|
}
|
|
15950
16004
|
function convertJSXMemberExpr(node) {
|
|
15951
16005
|
let object;
|
|
15952
16006
|
if (t.isJSXIdentifier(node.object)) {
|
|
15953
|
-
object = { kind: "Identifier", name: node.object.name };
|
|
16007
|
+
object = { kind: "Identifier", name: node.object.name, loc: getLoc(node.object) };
|
|
15954
16008
|
} else {
|
|
15955
16009
|
object = convertJSXMemberExpr(node.object);
|
|
15956
16010
|
}
|
|
15957
16011
|
return {
|
|
15958
16012
|
kind: "MemberExpression",
|
|
15959
16013
|
object,
|
|
15960
|
-
property: {
|
|
15961
|
-
|
|
16014
|
+
property: {
|
|
16015
|
+
kind: "Identifier",
|
|
16016
|
+
name: node.property.name,
|
|
16017
|
+
loc: getLoc(node.property)
|
|
16018
|
+
},
|
|
16019
|
+
computed: false,
|
|
16020
|
+
loc: getLoc(node)
|
|
15962
16021
|
};
|
|
15963
16022
|
}
|
|
15964
16023
|
|
|
@@ -18916,11 +18975,17 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
18916
18975
|
if (uniqueOutputNames.length === 0) {
|
|
18917
18976
|
ctx.helpersUsed.add("useEffect");
|
|
18918
18977
|
ctx.needsCtx = true;
|
|
18919
|
-
const
|
|
18978
|
+
const effectCallArgs = [
|
|
18920
18979
|
t2.identifier("__fictCtx"),
|
|
18921
|
-
t2.arrowFunctionExpression([], t2.blockStatement(bodyStatements))
|
|
18922
|
-
|
|
18923
|
-
|
|
18980
|
+
t2.arrowFunctionExpression([], t2.blockStatement(bodyStatements))
|
|
18981
|
+
];
|
|
18982
|
+
{
|
|
18983
|
+
const slot = reserveHookSlot(ctx);
|
|
18984
|
+
if (slot >= 0) {
|
|
18985
|
+
effectCallArgs.push(t2.numericLiteral(slot));
|
|
18986
|
+
}
|
|
18987
|
+
}
|
|
18988
|
+
const effectCall = t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), effectCallArgs);
|
|
18924
18989
|
statements.push(t2.expressionStatement(effectCall));
|
|
18925
18990
|
} else {
|
|
18926
18991
|
ctx.helpersUsed.add("useMemo");
|
|
@@ -18953,11 +19018,15 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
18953
19018
|
};
|
|
18954
19019
|
const returnObj = t2.objectExpression(uniqueOutputNames.map((name) => buildOutputProperty(name)));
|
|
18955
19020
|
const memoBody = t2.blockStatement([...bodyStatements, t2.returnStatement(returnObj)]);
|
|
18956
|
-
const
|
|
19021
|
+
const slot = reserveHookSlot(ctx);
|
|
19022
|
+
const memoArgs = [
|
|
18957
19023
|
t2.identifier("__fictCtx"),
|
|
18958
|
-
t2.arrowFunctionExpression([], memoBody)
|
|
18959
|
-
|
|
18960
|
-
|
|
19024
|
+
t2.arrowFunctionExpression([], memoBody)
|
|
19025
|
+
];
|
|
19026
|
+
if (slot >= 0) {
|
|
19027
|
+
memoArgs.push(t2.numericLiteral(slot));
|
|
19028
|
+
}
|
|
19029
|
+
const memoCall = t2.callExpression(t2.identifier(RUNTIME_ALIASES.useMemo), memoArgs);
|
|
18961
19030
|
const regionVarName = `__region_${region.id}`;
|
|
18962
19031
|
statements.push(
|
|
18963
19032
|
t2.variableDeclaration("const", [t2.variableDeclarator(t2.identifier(regionVarName), memoCall)])
|
|
@@ -19014,7 +19083,10 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
19014
19083
|
t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), [
|
|
19015
19084
|
t2.identifier("__fictCtx"),
|
|
19016
19085
|
t2.arrowFunctionExpression([], effectBody),
|
|
19017
|
-
|
|
19086
|
+
(() => {
|
|
19087
|
+
const slot2 = reserveHookSlot(ctx);
|
|
19088
|
+
return slot2 >= 0 ? t2.numericLiteral(slot2) : t2.identifier("undefined");
|
|
19089
|
+
})()
|
|
19018
19090
|
])
|
|
19019
19091
|
)
|
|
19020
19092
|
);
|
|
@@ -19232,11 +19304,15 @@ function generateLazyConditionalMemo(region, orderedOutputs, bodyStatements, con
|
|
|
19232
19304
|
ctx.helpersUsed.add("useMemo");
|
|
19233
19305
|
ctx.needsCtx = true;
|
|
19234
19306
|
const regionVarName = `__region_${region.id}`;
|
|
19235
|
-
const
|
|
19307
|
+
const slotForMemo = reserveHookSlot(ctx);
|
|
19308
|
+
const memoArgs = [
|
|
19236
19309
|
t2.identifier("__fictCtx"),
|
|
19237
|
-
t2.arrowFunctionExpression([], t2.blockStatement(memoBody))
|
|
19238
|
-
|
|
19239
|
-
|
|
19310
|
+
t2.arrowFunctionExpression([], t2.blockStatement(memoBody))
|
|
19311
|
+
];
|
|
19312
|
+
if (slotForMemo >= 0) {
|
|
19313
|
+
memoArgs.push(t2.numericLiteral(slotForMemo));
|
|
19314
|
+
}
|
|
19315
|
+
const memoCall = t2.callExpression(t2.identifier("__fictUseMemo"), memoArgs);
|
|
19240
19316
|
statements.push(
|
|
19241
19317
|
t2.variableDeclaration("const", [t2.variableDeclarator(t2.identifier(regionVarName), memoCall)])
|
|
19242
19318
|
);
|
|
@@ -19258,6 +19334,9 @@ function generateLazyConditionalMemo(region, orderedOutputs, bodyStatements, con
|
|
|
19258
19334
|
return statements;
|
|
19259
19335
|
}
|
|
19260
19336
|
function reserveHookSlot(ctx) {
|
|
19337
|
+
if (ctx.dynamicHookSlotDepth && ctx.dynamicHookSlotDepth > 0) {
|
|
19338
|
+
return -1;
|
|
19339
|
+
}
|
|
19261
19340
|
const slot = ctx.nextHookSlot ?? 0;
|
|
19262
19341
|
ctx.nextHookSlot = slot + 1;
|
|
19263
19342
|
return slot;
|
|
@@ -19328,7 +19407,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19328
19407
|
t2.arrowFunctionExpression([], expr)
|
|
19329
19408
|
];
|
|
19330
19409
|
if (inRegionMemo) {
|
|
19331
|
-
|
|
19410
|
+
const slot = reserveHookSlot(ctx);
|
|
19411
|
+
if (slot >= 0) {
|
|
19412
|
+
args.push(t2.numericLiteral(slot));
|
|
19413
|
+
}
|
|
19332
19414
|
}
|
|
19333
19415
|
ctx.helpersUsed.add("useMemo");
|
|
19334
19416
|
ctx.needsCtx = true;
|
|
@@ -19843,6 +19925,17 @@ function deSSAJSXChild(child, t2) {
|
|
|
19843
19925
|
// src/ir/codegen.ts
|
|
19844
19926
|
var HOOK_SLOT_BASE = 1e3;
|
|
19845
19927
|
var HOOK_NAME_PREFIX = "use";
|
|
19928
|
+
var cloneLoc = (loc) => loc === void 0 ? void 0 : loc === null ? null : {
|
|
19929
|
+
start: { ...loc.start },
|
|
19930
|
+
end: { ...loc.end },
|
|
19931
|
+
filename: loc.filename,
|
|
19932
|
+
identifierName: loc.identifierName
|
|
19933
|
+
};
|
|
19934
|
+
function setNodeLoc(node, loc) {
|
|
19935
|
+
if (loc === void 0) return node;
|
|
19936
|
+
node.loc = cloneLoc(loc) ?? null;
|
|
19937
|
+
return node;
|
|
19938
|
+
}
|
|
19846
19939
|
function isHookName(name) {
|
|
19847
19940
|
return !!name && name.startsWith(HOOK_NAME_PREFIX);
|
|
19848
19941
|
}
|
|
@@ -19876,13 +19969,22 @@ function applyRegionToContext(ctx, region) {
|
|
|
19876
19969
|
return prevRegion;
|
|
19877
19970
|
}
|
|
19878
19971
|
function reserveHookSlot2(ctx) {
|
|
19972
|
+
if (ctx.dynamicHookSlotDepth && ctx.dynamicHookSlotDepth > 0) {
|
|
19973
|
+
return -1;
|
|
19974
|
+
}
|
|
19879
19975
|
const slot = ctx.nextHookSlot ?? HOOK_SLOT_BASE;
|
|
19880
19976
|
ctx.nextHookSlot = slot + 1;
|
|
19881
19977
|
return slot;
|
|
19882
19978
|
}
|
|
19883
19979
|
function expressionContainsJSX(expr) {
|
|
19980
|
+
if (Array.isArray(expr)) {
|
|
19981
|
+
return expr.some((item) => expressionContainsJSX(item));
|
|
19982
|
+
}
|
|
19884
19983
|
if (!expr || typeof expr !== "object") return false;
|
|
19885
19984
|
if (expr.kind === "JSXElement") return true;
|
|
19985
|
+
if (Array.isArray(expr.instructions)) {
|
|
19986
|
+
return expr.instructions.some((i) => expressionContainsJSX(i?.value ?? i));
|
|
19987
|
+
}
|
|
19886
19988
|
switch (expr.kind) {
|
|
19887
19989
|
case "CallExpression":
|
|
19888
19990
|
if (expressionContainsJSX(expr.callee)) return true;
|
|
@@ -19895,10 +19997,29 @@ function expressionContainsJSX(expr) {
|
|
|
19895
19997
|
return expressionContainsJSX(expr.test) || expressionContainsJSX(expr.consequent) || expressionContainsJSX(expr.alternate);
|
|
19896
19998
|
case "ArrowFunction":
|
|
19897
19999
|
return expressionContainsJSX(expr.body);
|
|
20000
|
+
case "FunctionExpression":
|
|
20001
|
+
if (Array.isArray(expr.body)) {
|
|
20002
|
+
return expr.body.some(
|
|
20003
|
+
(block) => block.instructions?.some((i) => expressionContainsJSX(i.value))
|
|
20004
|
+
);
|
|
20005
|
+
}
|
|
20006
|
+
return false;
|
|
19898
20007
|
default:
|
|
19899
20008
|
return false;
|
|
19900
20009
|
}
|
|
19901
20010
|
}
|
|
20011
|
+
function withNoMemoAndDynamicHooks(ctx, fn) {
|
|
20012
|
+
const prevNoMemo = ctx.noMemo;
|
|
20013
|
+
const prevDynamic = ctx.dynamicHookSlotDepth ?? 0;
|
|
20014
|
+
ctx.noMemo = true;
|
|
20015
|
+
ctx.dynamicHookSlotDepth = prevDynamic + 1;
|
|
20016
|
+
try {
|
|
20017
|
+
return fn();
|
|
20018
|
+
} finally {
|
|
20019
|
+
ctx.noMemo = prevNoMemo;
|
|
20020
|
+
ctx.dynamicHookSlotDepth = prevDynamic;
|
|
20021
|
+
}
|
|
20022
|
+
}
|
|
19902
20023
|
function functionContainsJSX(fn) {
|
|
19903
20024
|
for (const block of fn.blocks) {
|
|
19904
20025
|
for (const instr of block.instructions) {
|
|
@@ -20997,18 +21118,25 @@ function lowerTrackedExpression(expr, ctx) {
|
|
|
20997
21118
|
}
|
|
20998
21119
|
function lowerInstruction(instr, ctx) {
|
|
20999
21120
|
const { t: t2 } = ctx;
|
|
21121
|
+
const applyLoc = (stmt) => {
|
|
21122
|
+
if (!stmt) return stmt;
|
|
21123
|
+
const baseLoc = instr.loc ?? (instr.kind === "Assign" || instr.kind === "Expression" ? instr.value.loc : void 0);
|
|
21124
|
+
return setNodeLoc(stmt, baseLoc);
|
|
21125
|
+
};
|
|
21000
21126
|
if (instr.kind === "Assign") {
|
|
21001
21127
|
const baseName2 = deSSAVarName(instr.target.name);
|
|
21002
21128
|
const isFunctionDecl = instr.value.kind === "FunctionExpression" && (instr.declarationKind === "function" || !instr.declarationKind && instr.value.name === baseName2);
|
|
21003
21129
|
if (isFunctionDecl) {
|
|
21004
21130
|
const loweredFn = lowerExpression(instr.value, ctx);
|
|
21005
21131
|
if (t2.isFunctionExpression(loweredFn)) {
|
|
21006
|
-
return
|
|
21007
|
-
t2.
|
|
21008
|
-
|
|
21009
|
-
|
|
21010
|
-
|
|
21011
|
-
|
|
21132
|
+
return applyLoc(
|
|
21133
|
+
t2.functionDeclaration(
|
|
21134
|
+
t2.identifier(baseName2),
|
|
21135
|
+
loweredFn.params,
|
|
21136
|
+
loweredFn.body,
|
|
21137
|
+
loweredFn.generator ?? false,
|
|
21138
|
+
loweredFn.async ?? false
|
|
21139
|
+
)
|
|
21012
21140
|
);
|
|
21013
21141
|
}
|
|
21014
21142
|
}
|
|
@@ -21023,12 +21151,16 @@ function lowerInstruction(instr, ctx) {
|
|
|
21023
21151
|
ctx.memoVars?.add(baseName2);
|
|
21024
21152
|
}
|
|
21025
21153
|
if (declKind) {
|
|
21026
|
-
return
|
|
21027
|
-
t2.
|
|
21028
|
-
|
|
21154
|
+
return applyLoc(
|
|
21155
|
+
t2.variableDeclaration(declKind, [
|
|
21156
|
+
t2.variableDeclarator(t2.identifier(baseName2), hookMember.member)
|
|
21157
|
+
])
|
|
21158
|
+
);
|
|
21029
21159
|
}
|
|
21030
|
-
return
|
|
21031
|
-
t2.
|
|
21160
|
+
return applyLoc(
|
|
21161
|
+
t2.expressionStatement(
|
|
21162
|
+
t2.assignmentExpression("=", t2.identifier(baseName2), hookMember.member)
|
|
21163
|
+
)
|
|
21032
21164
|
);
|
|
21033
21165
|
}
|
|
21034
21166
|
if (instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && isHookName(instr.value.callee.name)) {
|
|
@@ -21042,16 +21174,24 @@ function lowerInstruction(instr, ctx) {
|
|
|
21042
21174
|
}
|
|
21043
21175
|
}
|
|
21044
21176
|
if (ctx.signalVars?.has(baseName2)) {
|
|
21045
|
-
return
|
|
21046
|
-
t2.
|
|
21177
|
+
return applyLoc(
|
|
21178
|
+
t2.expressionStatement(
|
|
21179
|
+
t2.callExpression(t2.identifier(baseName2), [lowerTrackedExpression(instr.value, ctx)])
|
|
21180
|
+
)
|
|
21047
21181
|
);
|
|
21048
21182
|
}
|
|
21049
|
-
return
|
|
21050
|
-
t2.
|
|
21183
|
+
return applyLoc(
|
|
21184
|
+
t2.expressionStatement(
|
|
21185
|
+
t2.assignmentExpression(
|
|
21186
|
+
"=",
|
|
21187
|
+
t2.identifier(baseName2),
|
|
21188
|
+
lowerTrackedExpression(instr.value, ctx)
|
|
21189
|
+
)
|
|
21190
|
+
)
|
|
21051
21191
|
);
|
|
21052
21192
|
}
|
|
21053
21193
|
if (instr.kind === "Expression") {
|
|
21054
|
-
return t2.expressionStatement(lowerTrackedExpression(instr.value, ctx));
|
|
21194
|
+
return applyLoc(t2.expressionStatement(lowerTrackedExpression(instr.value, ctx)));
|
|
21055
21195
|
}
|
|
21056
21196
|
if (instr.kind === "Phi") {
|
|
21057
21197
|
return null;
|
|
@@ -21060,6 +21200,9 @@ function lowerInstruction(instr, ctx) {
|
|
|
21060
21200
|
}
|
|
21061
21201
|
function lowerTerminator(block, ctx) {
|
|
21062
21202
|
const { t: t2 } = ctx;
|
|
21203
|
+
const baseLoc = block.terminator.loc ?? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21204
|
+
block.terminator.argument?.loc;
|
|
21205
|
+
const applyLoc = (stmts) => stmts.map((stmt) => setNodeLoc(stmt, baseLoc));
|
|
21063
21206
|
switch (block.terminator.kind) {
|
|
21064
21207
|
case "Return": {
|
|
21065
21208
|
const prevRegion = ctx.currentRegion;
|
|
@@ -21072,14 +21215,14 @@ function lowerTerminator(block, ctx) {
|
|
|
21072
21215
|
}
|
|
21073
21216
|
ctx.inReturn = false;
|
|
21074
21217
|
ctx.currentRegion = prevRegion;
|
|
21075
|
-
return [t2.returnStatement(retExpr)];
|
|
21218
|
+
return applyLoc([t2.returnStatement(retExpr)]);
|
|
21076
21219
|
}
|
|
21077
21220
|
case "Throw":
|
|
21078
|
-
return [t2.throwStatement(lowerTrackedExpression(block.terminator.argument, ctx))];
|
|
21221
|
+
return applyLoc([t2.throwStatement(lowerTrackedExpression(block.terminator.argument, ctx))]);
|
|
21079
21222
|
case "Jump":
|
|
21080
|
-
return [t2.expressionStatement(t2.stringLiteral(`jump ${block.terminator.target}`))];
|
|
21223
|
+
return applyLoc([t2.expressionStatement(t2.stringLiteral(`jump ${block.terminator.target}`))]);
|
|
21081
21224
|
case "Branch":
|
|
21082
|
-
return [
|
|
21225
|
+
return applyLoc([
|
|
21083
21226
|
t2.ifStatement(
|
|
21084
21227
|
lowerTrackedExpression(block.terminator.test, ctx),
|
|
21085
21228
|
t2.blockStatement([
|
|
@@ -21089,9 +21232,9 @@ function lowerTerminator(block, ctx) {
|
|
|
21089
21232
|
t2.expressionStatement(t2.stringLiteral(`goto ${block.terminator.alternate}`))
|
|
21090
21233
|
])
|
|
21091
21234
|
)
|
|
21092
|
-
];
|
|
21235
|
+
]);
|
|
21093
21236
|
case "Switch":
|
|
21094
|
-
return [
|
|
21237
|
+
return applyLoc([
|
|
21095
21238
|
t2.switchStatement(
|
|
21096
21239
|
lowerTrackedExpression(block.terminator.discriminant, ctx),
|
|
21097
21240
|
block.terminator.cases.map(
|
|
@@ -21100,30 +21243,30 @@ function lowerTerminator(block, ctx) {
|
|
|
21100
21243
|
])
|
|
21101
21244
|
)
|
|
21102
21245
|
)
|
|
21103
|
-
];
|
|
21246
|
+
]);
|
|
21104
21247
|
case "ForOf": {
|
|
21105
21248
|
const term = block.terminator;
|
|
21106
21249
|
const varKind = term.variableKind ?? "const";
|
|
21107
21250
|
const leftPattern = term.pattern ? term.pattern : t2.identifier(term.variable);
|
|
21108
|
-
return [
|
|
21251
|
+
return applyLoc([
|
|
21109
21252
|
t2.forOfStatement(
|
|
21110
21253
|
t2.variableDeclaration(varKind, [t2.variableDeclarator(leftPattern)]),
|
|
21111
21254
|
lowerExpression(term.iterable, ctx),
|
|
21112
21255
|
t2.blockStatement([t2.expressionStatement(t2.stringLiteral(`body ${term.body}`))])
|
|
21113
21256
|
)
|
|
21114
|
-
];
|
|
21257
|
+
]);
|
|
21115
21258
|
}
|
|
21116
21259
|
case "ForIn": {
|
|
21117
21260
|
const term = block.terminator;
|
|
21118
21261
|
const varKind = term.variableKind ?? "const";
|
|
21119
21262
|
const leftPattern = term.pattern ? term.pattern : t2.identifier(term.variable);
|
|
21120
|
-
return [
|
|
21263
|
+
return applyLoc([
|
|
21121
21264
|
t2.forInStatement(
|
|
21122
21265
|
t2.variableDeclaration(varKind, [t2.variableDeclarator(leftPattern)]),
|
|
21123
21266
|
lowerExpression(term.object, ctx),
|
|
21124
21267
|
t2.blockStatement([t2.expressionStatement(t2.stringLiteral(`body ${term.body}`))])
|
|
21125
21268
|
)
|
|
21126
|
-
];
|
|
21269
|
+
]);
|
|
21127
21270
|
}
|
|
21128
21271
|
case "Try": {
|
|
21129
21272
|
const term = block.terminator;
|
|
@@ -21139,20 +21282,20 @@ function lowerTerminator(block, ctx) {
|
|
|
21139
21282
|
const finallyBlock = term.finallyBlock !== void 0 ? t2.blockStatement([
|
|
21140
21283
|
t2.expressionStatement(t2.stringLiteral(`finally ${term.finallyBlock}`))
|
|
21141
21284
|
]) : null;
|
|
21142
|
-
return [t2.tryStatement(tryBlock, catchClause, finallyBlock)];
|
|
21285
|
+
return applyLoc([t2.tryStatement(tryBlock, catchClause, finallyBlock)]);
|
|
21143
21286
|
}
|
|
21144
21287
|
case "Unreachable":
|
|
21145
|
-
return [];
|
|
21288
|
+
return applyLoc([]);
|
|
21146
21289
|
case "Break":
|
|
21147
|
-
return [
|
|
21290
|
+
return applyLoc([
|
|
21148
21291
|
t2.breakStatement(block.terminator.label ? t2.identifier(block.terminator.label) : null)
|
|
21149
|
-
];
|
|
21292
|
+
]);
|
|
21150
21293
|
case "Continue":
|
|
21151
|
-
return [
|
|
21294
|
+
return applyLoc([
|
|
21152
21295
|
t2.continueStatement(block.terminator.label ? t2.identifier(block.terminator.label) : null)
|
|
21153
|
-
];
|
|
21296
|
+
]);
|
|
21154
21297
|
default:
|
|
21155
|
-
return [];
|
|
21298
|
+
return applyLoc([]);
|
|
21156
21299
|
}
|
|
21157
21300
|
}
|
|
21158
21301
|
function attachHelperImports(ctx, body, t2) {
|
|
@@ -21291,7 +21434,7 @@ function lowerExpression(expr, ctx, isAssigned = false) {
|
|
|
21291
21434
|
}
|
|
21292
21435
|
ctx.expressionDepth = depth;
|
|
21293
21436
|
try {
|
|
21294
|
-
return lowerExpressionImpl(expr, ctx, isAssigned);
|
|
21437
|
+
return setNodeLoc(lowerExpressionImpl(expr, ctx, isAssigned), expr.loc);
|
|
21295
21438
|
} finally {
|
|
21296
21439
|
ctx.expressionDepth = depth - 1;
|
|
21297
21440
|
}
|
|
@@ -21426,14 +21569,22 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21426
21569
|
const calleeIsMemoAccessor = !!calleeName && ctx.memoVars?.has(calleeName);
|
|
21427
21570
|
const calleeIsSignalLike = !!calleeName && (ctx.signalVars?.has(calleeName) || ctx.storeVars?.has(calleeName));
|
|
21428
21571
|
if (calleeIsMemoAccessor && !calleeIsSignalLike && expr.arguments.length > 0) {
|
|
21429
|
-
const
|
|
21430
|
-
return t2.callExpression(t2.callExpression(t2.identifier(calleeName), []),
|
|
21572
|
+
const loweredArgs2 = expr.arguments.map((a) => lowerExpression(a, ctx));
|
|
21573
|
+
return t2.callExpression(t2.callExpression(t2.identifier(calleeName), []), loweredArgs2);
|
|
21431
21574
|
}
|
|
21432
21575
|
const lowerCallee = () => isIIFE ? withNonReactiveScope(ctx, () => lowerExpression(expr.callee, ctx)) : lowerExpression(expr.callee, ctx);
|
|
21433
|
-
|
|
21434
|
-
|
|
21435
|
-
|
|
21436
|
-
|
|
21576
|
+
const isIteratingMethod = expr.callee.kind === "MemberExpression" && (expr.callee.property.kind === "Identifier" && ["map", "reduce", "forEach", "filter", "flatMap", "some", "every", "find"].includes(
|
|
21577
|
+
expr.callee.property.name
|
|
21578
|
+
) || expr.callee.property.kind === "Literal" && ["map", "reduce", "forEach", "filter", "flatMap", "some", "every", "find"].includes(
|
|
21579
|
+
String(expr.callee.property.value)
|
|
21580
|
+
));
|
|
21581
|
+
const loweredArgs = expr.arguments.map((a, idx) => {
|
|
21582
|
+
if (idx === 0 && isIteratingMethod && (a.kind === "ArrowFunction" || a.kind === "FunctionExpression")) {
|
|
21583
|
+
return withNoMemoAndDynamicHooks(ctx, () => lowerExpression(a, ctx));
|
|
21584
|
+
}
|
|
21585
|
+
return lowerExpression(a, ctx);
|
|
21586
|
+
});
|
|
21587
|
+
return t2.callExpression(lowerCallee(), loweredArgs);
|
|
21437
21588
|
}
|
|
21438
21589
|
case "MemberExpression":
|
|
21439
21590
|
if (matchesListKeyPattern(expr, ctx)) {
|
|
@@ -22290,15 +22441,6 @@ function isStaticValue(expr) {
|
|
|
22290
22441
|
if (!expr) return false;
|
|
22291
22442
|
return expr.kind === "Literal";
|
|
22292
22443
|
}
|
|
22293
|
-
function isComponentLikeCallee(expr) {
|
|
22294
|
-
if (expr.kind === "Identifier") {
|
|
22295
|
-
return expr.name[0] === expr.name[0]?.toUpperCase();
|
|
22296
|
-
}
|
|
22297
|
-
if (expr.kind === "MemberExpression" || expr.kind === "OptionalMemberExpression") {
|
|
22298
|
-
return isComponentLikeCallee(expr.object);
|
|
22299
|
-
}
|
|
22300
|
-
return false;
|
|
22301
|
-
}
|
|
22302
22444
|
function isLikelyTextExpression(expr, ctx) {
|
|
22303
22445
|
let ok = true;
|
|
22304
22446
|
const isReactiveIdentifier = (name) => {
|
|
@@ -22327,15 +22469,9 @@ function isLikelyTextExpression(expr, ctx) {
|
|
|
22327
22469
|
ok = false;
|
|
22328
22470
|
return;
|
|
22329
22471
|
case "CallExpression":
|
|
22330
|
-
case "OptionalCallExpression":
|
|
22331
|
-
|
|
22332
|
-
ok = false;
|
|
22333
|
-
return;
|
|
22334
|
-
}
|
|
22335
|
-
visit(node.callee, true);
|
|
22336
|
-
node.arguments.forEach((arg) => visit(arg));
|
|
22472
|
+
case "OptionalCallExpression":
|
|
22473
|
+
ok = false;
|
|
22337
22474
|
return;
|
|
22338
|
-
}
|
|
22339
22475
|
case "MemberExpression":
|
|
22340
22476
|
case "OptionalMemberExpression":
|
|
22341
22477
|
visit(node.object, true);
|
|
@@ -22790,7 +22926,12 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
22790
22926
|
t2.arrowFunctionExpression([], body)
|
|
22791
22927
|
];
|
|
22792
22928
|
if (ctx.isComponentFn) {
|
|
22793
|
-
|
|
22929
|
+
{
|
|
22930
|
+
const slot = reserveHookSlot2(ctx);
|
|
22931
|
+
if (slot >= 0) {
|
|
22932
|
+
memoArgs.push(t2.numericLiteral(slot));
|
|
22933
|
+
}
|
|
22934
|
+
}
|
|
22794
22935
|
}
|
|
22795
22936
|
return t2.callExpression(t2.callExpression(t2.identifier(RUNTIME_ALIASES.useMemo), memoArgs), []);
|
|
22796
22937
|
}
|
|
@@ -23345,12 +23486,16 @@ function emitListChild(parentId, markerId, expr, statements, ctx) {
|
|
|
23345
23486
|
const hoistedStatements = ctx.hoistedTemplateStatements;
|
|
23346
23487
|
ctx.hoistedTemplates = prevHoistedTemplates;
|
|
23347
23488
|
ctx.hoistedTemplateStatements = prevHoistedTemplateStatements;
|
|
23348
|
-
if (
|
|
23349
|
-
const firstParam = callbackExpr.params
|
|
23489
|
+
if (t2.isArrowFunctionExpression(callbackExpr) || t2.isFunctionExpression(callbackExpr)) {
|
|
23490
|
+
const [firstParam, secondParam] = callbackExpr.params;
|
|
23491
|
+
const overrides = {};
|
|
23350
23492
|
if (t2.isIdentifier(firstParam)) {
|
|
23351
|
-
|
|
23352
|
-
|
|
23353
|
-
|
|
23493
|
+
overrides[firstParam.name] = () => t2.callExpression(t2.identifier(firstParam.name), []);
|
|
23494
|
+
}
|
|
23495
|
+
if (t2.isIdentifier(secondParam)) {
|
|
23496
|
+
overrides[secondParam.name] = () => t2.callExpression(t2.identifier(secondParam.name), []);
|
|
23497
|
+
}
|
|
23498
|
+
if (Object.keys(overrides).length > 0) {
|
|
23354
23499
|
if (t2.isBlockStatement(callbackExpr.body)) {
|
|
23355
23500
|
replaceIdentifiersWithOverrides(callbackExpr.body, overrides, t2, callbackExpr.type, "body");
|
|
23356
23501
|
} else {
|
|
@@ -24244,10 +24389,9 @@ function lowerFunctionWithRegions(fn, ctx) {
|
|
|
24244
24389
|
}
|
|
24245
24390
|
}
|
|
24246
24391
|
const params = finalParams;
|
|
24247
|
-
const funcDecl =
|
|
24248
|
-
t2.identifier(fn.name ?? "fn"),
|
|
24249
|
-
|
|
24250
|
-
t2.blockStatement(statements)
|
|
24392
|
+
const funcDecl = setNodeLoc(
|
|
24393
|
+
t2.functionDeclaration(t2.identifier(fn.name ?? "fn"), params, t2.blockStatement(statements)),
|
|
24394
|
+
fn.loc
|
|
24251
24395
|
);
|
|
24252
24396
|
ctx.needsCtx = prevNeedsCtx;
|
|
24253
24397
|
ctx.shadowedNames = prevShadowed;
|
|
@@ -24336,10 +24480,44 @@ function isInsideNestedFunction(path) {
|
|
|
24336
24480
|
function isInsideJSX(path) {
|
|
24337
24481
|
return !!path.findParent((p) => p.isJSXElement?.() || p.isJSXFragment?.());
|
|
24338
24482
|
}
|
|
24339
|
-
function
|
|
24340
|
-
if (!
|
|
24483
|
+
function parseSuppressionCodes(raw) {
|
|
24484
|
+
if (!raw) return void 0;
|
|
24485
|
+
const codes = raw.split(/[,\s]+/).map((c) => c.trim()).filter(Boolean);
|
|
24486
|
+
return codes.length > 0 ? new Set(codes) : void 0;
|
|
24487
|
+
}
|
|
24488
|
+
function parseSuppressions(comments) {
|
|
24489
|
+
if (!comments) return [];
|
|
24490
|
+
const suppressions = [];
|
|
24491
|
+
for (const comment of comments) {
|
|
24492
|
+
const match = comment.value.match(/fict-ignore(-next-line)?(?:\s+(.+))?/i);
|
|
24493
|
+
if (!match || !comment.loc) continue;
|
|
24494
|
+
suppressions.push({
|
|
24495
|
+
line: comment.loc.start.line,
|
|
24496
|
+
nextLine: !!match[1],
|
|
24497
|
+
codes: parseSuppressionCodes(match[2])
|
|
24498
|
+
});
|
|
24499
|
+
}
|
|
24500
|
+
return suppressions;
|
|
24501
|
+
}
|
|
24502
|
+
function shouldSuppressWarning(suppressions, code, line) {
|
|
24503
|
+
return suppressions.some((entry) => {
|
|
24504
|
+
const targetLine = entry.nextLine ? entry.line + 1 : entry.line;
|
|
24505
|
+
if (targetLine !== line) return false;
|
|
24506
|
+
if (!entry.codes || entry.codes.size === 0) return true;
|
|
24507
|
+
return entry.codes.has(code);
|
|
24508
|
+
});
|
|
24509
|
+
}
|
|
24510
|
+
function createWarningDispatcher(onWarn, suppressions) {
|
|
24511
|
+
if (!onWarn) return () => {
|
|
24512
|
+
};
|
|
24513
|
+
return (warning) => {
|
|
24514
|
+
if (shouldSuppressWarning(suppressions, warning.code, warning.line)) return;
|
|
24515
|
+
onWarn(warning);
|
|
24516
|
+
};
|
|
24517
|
+
}
|
|
24518
|
+
function emitWarning(node, code, message, warn, fileName) {
|
|
24341
24519
|
const loc = node.loc?.start;
|
|
24342
|
-
|
|
24520
|
+
warn({
|
|
24343
24521
|
code,
|
|
24344
24522
|
message,
|
|
24345
24523
|
fileName,
|
|
@@ -24427,8 +24605,7 @@ function isDynamicPropertyAccess(node, t2) {
|
|
|
24427
24605
|
if (!node.computed) return false;
|
|
24428
24606
|
return !(t2.isStringLiteral(node.property) || t2.isNumericLiteral(node.property));
|
|
24429
24607
|
}
|
|
24430
|
-
function runWarningPass(programPath, stateVars, derivedVars,
|
|
24431
|
-
const fileName = programPath.hub?.file?.opts?.filename || "<unknown>";
|
|
24608
|
+
function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t2) {
|
|
24432
24609
|
const isStateRoot = (expr) => {
|
|
24433
24610
|
const root = getRootIdentifier(expr, t2);
|
|
24434
24611
|
return !!(root && stateVars.has(root.name));
|
|
@@ -24444,7 +24621,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24444
24621
|
path.node,
|
|
24445
24622
|
"FICT-M",
|
|
24446
24623
|
"Direct mutation of nested property detected; use immutable update or $store helpers",
|
|
24447
|
-
|
|
24624
|
+
warn,
|
|
24448
24625
|
fileName
|
|
24449
24626
|
);
|
|
24450
24627
|
if (isDynamicPropertyAccess(left, t2)) {
|
|
@@ -24452,7 +24629,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24452
24629
|
path.node,
|
|
24453
24630
|
"FICT-H",
|
|
24454
24631
|
"Dynamic property access widens dependency tracking",
|
|
24455
|
-
|
|
24632
|
+
warn,
|
|
24456
24633
|
fileName
|
|
24457
24634
|
);
|
|
24458
24635
|
}
|
|
@@ -24467,7 +24644,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24467
24644
|
path.node,
|
|
24468
24645
|
"FICT-M",
|
|
24469
24646
|
"Direct mutation of nested property detected; use immutable update or $store helpers",
|
|
24470
|
-
|
|
24647
|
+
warn,
|
|
24471
24648
|
fileName
|
|
24472
24649
|
);
|
|
24473
24650
|
if (isDynamicPropertyAccess(arg, t2)) {
|
|
@@ -24475,7 +24652,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24475
24652
|
path.node,
|
|
24476
24653
|
"FICT-H",
|
|
24477
24654
|
"Dynamic property access widens dependency tracking",
|
|
24478
|
-
|
|
24655
|
+
warn,
|
|
24479
24656
|
fileName
|
|
24480
24657
|
);
|
|
24481
24658
|
}
|
|
@@ -24491,7 +24668,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24491
24668
|
path.node,
|
|
24492
24669
|
"FICT-H",
|
|
24493
24670
|
"Dynamic property access widens dependency tracking",
|
|
24494
|
-
|
|
24671
|
+
warn,
|
|
24495
24672
|
fileName
|
|
24496
24673
|
);
|
|
24497
24674
|
}
|
|
@@ -24520,7 +24697,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24520
24697
|
path.node,
|
|
24521
24698
|
"FICT-R005",
|
|
24522
24699
|
`Function captures reactive variable(s): ${Array.from(captured).join(", ")}. Pass them as parameters or memoize explicitly to avoid hidden dependencies.`,
|
|
24523
|
-
|
|
24700
|
+
warn,
|
|
24524
24701
|
fileName
|
|
24525
24702
|
);
|
|
24526
24703
|
}
|
|
@@ -24551,7 +24728,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24551
24728
|
path.node,
|
|
24552
24729
|
"FICT-E001",
|
|
24553
24730
|
"Effect has no reactive reads; it will run once. Consider removing $effect or adding dependencies.",
|
|
24554
|
-
|
|
24731
|
+
warn,
|
|
24555
24732
|
fileName
|
|
24556
24733
|
);
|
|
24557
24734
|
}
|
|
@@ -24577,7 +24754,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24577
24754
|
arg,
|
|
24578
24755
|
"FICT-H",
|
|
24579
24756
|
"State value passed to unknown function (black box); dependency tracking may be imprecise",
|
|
24580
|
-
|
|
24757
|
+
warn,
|
|
24581
24758
|
fileName
|
|
24582
24759
|
);
|
|
24583
24760
|
break;
|
|
@@ -24593,7 +24770,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24593
24770
|
path.node,
|
|
24594
24771
|
"FICT-H",
|
|
24595
24772
|
"Dynamic property access widens dependency tracking",
|
|
24596
|
-
|
|
24773
|
+
warn,
|
|
24597
24774
|
fileName
|
|
24598
24775
|
);
|
|
24599
24776
|
}
|
|
@@ -24643,6 +24820,10 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24643
24820
|
Program: {
|
|
24644
24821
|
exit(path) {
|
|
24645
24822
|
const fileName = path.hub?.file?.opts?.filename || "<unknown>";
|
|
24823
|
+
const comments = path.hub?.file?.ast?.comments || [];
|
|
24824
|
+
const suppressions = parseSuppressions(comments);
|
|
24825
|
+
const warn = createWarningDispatcher(options.onWarn, suppressions);
|
|
24826
|
+
const optionsWithWarnings = { ...options, onWarn: warn };
|
|
24646
24827
|
const isHookName2 = (name) => !!name && /^use[A-Z]/.test(name);
|
|
24647
24828
|
const getFunctionName = (fnPath) => {
|
|
24648
24829
|
return fnPath.isFunctionDeclaration() && fnPath.node.id ? fnPath.node.id.name : fnPath.isFunctionExpression() && fnPath.node.id ? fnPath.node.id.name : fnPath.parentPath.isVariableDeclarator() && t2.isIdentifier(fnPath.parentPath.node.id) && fnPath.parentPath.node.init === fnPath.node ? fnPath.parentPath.node.id.name : void 0;
|
|
@@ -24661,14 +24842,75 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24661
24842
|
return name && isComponentName(name) || isHookName2(name) || functionHasJSX(fnPath) || functionUsesStateLike(fnPath, t2);
|
|
24662
24843
|
};
|
|
24663
24844
|
const memoHasSideEffects = (fn) => {
|
|
24845
|
+
const pureCalls = new Set(
|
|
24846
|
+
Array.from(SAFE_FUNCTIONS).filter(
|
|
24847
|
+
(name) => !name.startsWith("console.") && name !== "Math.random"
|
|
24848
|
+
)
|
|
24849
|
+
);
|
|
24850
|
+
const effectfulCalls = /* @__PURE__ */ new Set([
|
|
24851
|
+
"$effect",
|
|
24852
|
+
"render",
|
|
24853
|
+
"fetch",
|
|
24854
|
+
"setTimeout",
|
|
24855
|
+
"setInterval",
|
|
24856
|
+
"clearTimeout",
|
|
24857
|
+
"clearInterval",
|
|
24858
|
+
"requestAnimationFrame",
|
|
24859
|
+
"cancelAnimationFrame"
|
|
24860
|
+
]);
|
|
24861
|
+
const getCalleeName = (callee) => {
|
|
24862
|
+
if (t2.isIdentifier(callee)) return callee.name;
|
|
24863
|
+
if (t2.isMemberExpression(callee) && !callee.computed && t2.isIdentifier(callee.property) && t2.isIdentifier(callee.object)) {
|
|
24864
|
+
return `${callee.object.name}.${callee.property.name}`;
|
|
24865
|
+
}
|
|
24866
|
+
return null;
|
|
24867
|
+
};
|
|
24868
|
+
const mutatingMemberProps = /* @__PURE__ */ new Set([
|
|
24869
|
+
"push",
|
|
24870
|
+
"pop",
|
|
24871
|
+
"splice",
|
|
24872
|
+
"shift",
|
|
24873
|
+
"unshift",
|
|
24874
|
+
"sort",
|
|
24875
|
+
"reverse",
|
|
24876
|
+
"set",
|
|
24877
|
+
"add",
|
|
24878
|
+
"delete",
|
|
24879
|
+
"append",
|
|
24880
|
+
"appendChild",
|
|
24881
|
+
"remove",
|
|
24882
|
+
"removeChild",
|
|
24883
|
+
"setAttribute",
|
|
24884
|
+
"dispatchEvent",
|
|
24885
|
+
"replaceChildren",
|
|
24886
|
+
"replaceWith"
|
|
24887
|
+
]);
|
|
24888
|
+
const isEffectfulCall = (node) => {
|
|
24889
|
+
const name = getCalleeName(node.callee);
|
|
24890
|
+
if (!name) return true;
|
|
24891
|
+
if (pureCalls.has(name)) return false;
|
|
24892
|
+
if (effectfulCalls.has(name)) return true;
|
|
24893
|
+
if (name.startsWith("console.") || name.startsWith("document.") || name.startsWith("window.")) {
|
|
24894
|
+
return true;
|
|
24895
|
+
}
|
|
24896
|
+
if (t2.isMemberExpression(node.callee) && !node.callee.computed && t2.isIdentifier(node.callee.property)) {
|
|
24897
|
+
const prop = node.callee.property.name;
|
|
24898
|
+
if (mutatingMemberProps.has(prop)) return true;
|
|
24899
|
+
if (t2.isIdentifier(node.callee.object) && (node.callee.object.name === "document" || node.callee.object.name === "window")) {
|
|
24900
|
+
return true;
|
|
24901
|
+
}
|
|
24902
|
+
}
|
|
24903
|
+
return false;
|
|
24904
|
+
};
|
|
24664
24905
|
const checkNode = (node) => {
|
|
24665
24906
|
if (!node) return false;
|
|
24666
24907
|
if (t2.isAssignmentExpression(node) || t2.isUpdateExpression(node) || t2.isThrowStatement(node) || t2.isNewExpression(node)) {
|
|
24667
24908
|
return true;
|
|
24668
24909
|
}
|
|
24669
|
-
if (t2.isCallExpression(node) && (
|
|
24910
|
+
if (t2.isCallExpression(node) && isEffectfulCall(node)) {
|
|
24670
24911
|
return true;
|
|
24671
24912
|
}
|
|
24913
|
+
if (t2.isAwaitExpression(node)) return true;
|
|
24672
24914
|
if (t2.isExpressionStatement(node)) return checkNode(node.expression);
|
|
24673
24915
|
if (t2.isBlockStatement(node)) return node.body.some((stmt) => checkNode(stmt));
|
|
24674
24916
|
if (t2.isReturnStatement(node)) return checkNode(node.argument);
|
|
@@ -24692,7 +24934,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24692
24934
|
fnPath.node,
|
|
24693
24935
|
"FICT-C004",
|
|
24694
24936
|
"Component has no return statement and will render nothing.",
|
|
24695
|
-
|
|
24937
|
+
warn,
|
|
24696
24938
|
fileName
|
|
24697
24939
|
);
|
|
24698
24940
|
},
|
|
@@ -24710,7 +24952,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24710
24952
|
init,
|
|
24711
24953
|
"FICT-C004",
|
|
24712
24954
|
"Component has no return statement and will render nothing.",
|
|
24713
|
-
|
|
24955
|
+
warn,
|
|
24714
24956
|
fileName
|
|
24715
24957
|
);
|
|
24716
24958
|
}
|
|
@@ -24760,7 +25002,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24760
25002
|
}
|
|
24761
25003
|
}
|
|
24762
25004
|
if (hasKey || hasUnknownSpread) return;
|
|
24763
|
-
|
|
25005
|
+
warn({
|
|
24764
25006
|
code: "FICT-J002",
|
|
24765
25007
|
message: "Missing key prop in list rendering.",
|
|
24766
25008
|
fileName,
|
|
@@ -24831,7 +25073,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24831
25073
|
fnPath.node,
|
|
24832
25074
|
"FICT-C003",
|
|
24833
25075
|
"Components should not be defined inside other components. Move this definition to module scope to preserve identity and performance.",
|
|
24834
|
-
|
|
25076
|
+
warn,
|
|
24835
25077
|
fileName
|
|
24836
25078
|
);
|
|
24837
25079
|
},
|
|
@@ -24876,7 +25118,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24876
25118
|
callPath.node,
|
|
24877
25119
|
"FICT-R004",
|
|
24878
25120
|
"Reactive creation inside non-JSX control flow will not auto-dispose; wrap it in createScope/runInScope or move it into JSX-managed regions.",
|
|
24879
|
-
|
|
25121
|
+
warn,
|
|
24880
25122
|
fileName
|
|
24881
25123
|
);
|
|
24882
25124
|
}
|
|
@@ -24911,7 +25153,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24911
25153
|
callPath.node.arguments.forEach((arg) => {
|
|
24912
25154
|
if (t2.isIdentifier(arg) && stateVars.has(arg.name) && (!calleeId || !allowedStateCallees.has(calleeId))) {
|
|
24913
25155
|
const loc = arg.loc?.start ?? callPath.node.loc?.start;
|
|
24914
|
-
|
|
25156
|
+
warn({
|
|
24915
25157
|
code: "FICT-S002",
|
|
24916
25158
|
message: "State variable is passed as an argument; this passes a value snapshot and may escape component scope.",
|
|
24917
25159
|
fileName,
|
|
@@ -24924,7 +25166,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24924
25166
|
const firstArg = callPath.node.arguments[0];
|
|
24925
25167
|
if (firstArg && (t2.isArrowFunctionExpression(firstArg) || t2.isFunctionExpression(firstArg)) && memoHasSideEffects(firstArg)) {
|
|
24926
25168
|
const loc = firstArg.loc?.start ?? callPath.node.loc?.start;
|
|
24927
|
-
|
|
25169
|
+
warn({
|
|
24928
25170
|
code: "FICT-M003",
|
|
24929
25171
|
message: "Memo should not contain side effects.",
|
|
24930
25172
|
fileName,
|
|
@@ -25029,10 +25271,10 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
25029
25271
|
}
|
|
25030
25272
|
});
|
|
25031
25273
|
}
|
|
25032
|
-
runWarningPass(path, stateVars, derivedVars,
|
|
25274
|
+
runWarningPass(path, stateVars, derivedVars, warn, fileName, t2);
|
|
25033
25275
|
const fileAst = t2.file(path.node);
|
|
25034
25276
|
const hir = buildHIR(fileAst);
|
|
25035
|
-
const lowered = lowerHIRWithRegions(hir, t2,
|
|
25277
|
+
const lowered = lowerHIRWithRegions(hir, t2, optionsWithWarnings);
|
|
25036
25278
|
path.node.body = lowered.program.body;
|
|
25037
25279
|
path.node.directives = lowered.program.directives;
|
|
25038
25280
|
if (!process.env.FICT_SKIP_SCOPE_CRAWL) {
|