@fictjs/compiler 0.0.8 → 0.0.10
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 +522 -230
- package/dist/index.js +522 -230
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -14384,6 +14384,9 @@ function pathToString(path) {
|
|
|
14384
14384
|
|
|
14385
14385
|
// src/ir/build-hir.ts
|
|
14386
14386
|
var destructuringTempCounter = 0;
|
|
14387
|
+
var getLoc = (node) => {
|
|
14388
|
+
return node?.loc ?? null;
|
|
14389
|
+
};
|
|
14387
14390
|
function normalizeVarKind(kind) {
|
|
14388
14391
|
return kind === "const" || kind === "let" || kind === "var" ? kind : "let";
|
|
14389
14392
|
}
|
|
@@ -14453,7 +14456,8 @@ function buildHIR(ast) {
|
|
|
14453
14456
|
functions.push(
|
|
14454
14457
|
convertFunction(name, stmt.params, stmt.body.body, {
|
|
14455
14458
|
noMemo: programNoMemo,
|
|
14456
|
-
directives: stmt.body.directives
|
|
14459
|
+
directives: stmt.body.directives,
|
|
14460
|
+
loc: getLoc(stmt)
|
|
14457
14461
|
})
|
|
14458
14462
|
);
|
|
14459
14463
|
continue;
|
|
@@ -14466,7 +14470,8 @@ function buildHIR(ast) {
|
|
|
14466
14470
|
functions.push(
|
|
14467
14471
|
convertFunction(name, decl.params, decl.body.body, {
|
|
14468
14472
|
noMemo: programNoMemo,
|
|
14469
|
-
directives: decl.body.directives
|
|
14473
|
+
directives: decl.body.directives,
|
|
14474
|
+
loc: getLoc(decl)
|
|
14470
14475
|
})
|
|
14471
14476
|
);
|
|
14472
14477
|
postamble.push({ kind: "ExportFunction", name });
|
|
@@ -14484,9 +14489,11 @@ function buildHIR(ast) {
|
|
|
14484
14489
|
const hasExpressionBody = isArrow && !t.isBlockStatement(body);
|
|
14485
14490
|
const fnHIR = t.isBlockStatement(body) ? convertFunction(name, params, body.body, {
|
|
14486
14491
|
noMemo: programNoMemo,
|
|
14487
|
-
directives: body.directives
|
|
14492
|
+
directives: body.directives,
|
|
14493
|
+
loc: getLoc(v.init ?? v)
|
|
14488
14494
|
}) : convertFunction(name, params, [t.returnStatement(body)], {
|
|
14489
|
-
noMemo: programNoMemo
|
|
14495
|
+
noMemo: programNoMemo,
|
|
14496
|
+
loc: getLoc(v.init ?? v)
|
|
14490
14497
|
});
|
|
14491
14498
|
fnHIR.meta = { ...fnHIR.meta ?? {}, fromExpression: true, isArrow, hasExpressionBody };
|
|
14492
14499
|
functions.push(fnHIR);
|
|
@@ -14511,7 +14518,8 @@ function buildHIR(ast) {
|
|
|
14511
14518
|
functions.push(
|
|
14512
14519
|
convertFunction(name, decl.params, decl.body.body, {
|
|
14513
14520
|
noMemo: programNoMemo,
|
|
14514
|
-
directives: decl.body.directives
|
|
14521
|
+
directives: decl.body.directives,
|
|
14522
|
+
loc: getLoc(decl)
|
|
14515
14523
|
})
|
|
14516
14524
|
);
|
|
14517
14525
|
postamble.push({ kind: "ExportDefault", name });
|
|
@@ -14536,13 +14544,15 @@ function buildHIR(ast) {
|
|
|
14536
14544
|
const hasExpressionBody = isArrow && !t.isBlockStatement(body);
|
|
14537
14545
|
const fnHIR = t.isBlockStatement(body) ? convertFunction(name, params, body.body, {
|
|
14538
14546
|
noMemo: programNoMemo,
|
|
14539
|
-
directives: body.directives
|
|
14547
|
+
directives: body.directives,
|
|
14548
|
+
loc: getLoc(decl.init ?? decl)
|
|
14540
14549
|
}) : convertFunction(
|
|
14541
14550
|
name,
|
|
14542
14551
|
params,
|
|
14543
14552
|
[t.returnStatement(body)],
|
|
14544
14553
|
{
|
|
14545
|
-
noMemo: programNoMemo
|
|
14554
|
+
noMemo: programNoMemo,
|
|
14555
|
+
loc: getLoc(decl.init ?? decl)
|
|
14546
14556
|
}
|
|
14547
14557
|
);
|
|
14548
14558
|
fnHIR.meta = { ...fnHIR.meta ?? {}, fromExpression: true, isArrow, hasExpressionBody };
|
|
@@ -15050,11 +15060,12 @@ function convertFunction(name, params, body, options) {
|
|
|
15050
15060
|
name,
|
|
15051
15061
|
params: paramIds,
|
|
15052
15062
|
blocks,
|
|
15053
|
-
meta: hasNoMemo ? { noMemo: true } : void 0
|
|
15063
|
+
meta: hasNoMemo ? { noMemo: true } : void 0,
|
|
15064
|
+
loc: options?.loc ?? null
|
|
15054
15065
|
};
|
|
15055
15066
|
}
|
|
15056
15067
|
function convertStatementsToHIRFunction(name, statements) {
|
|
15057
|
-
return convertFunction(name, [], statements);
|
|
15068
|
+
return convertFunction(name, [], statements, { loc: getLoc(statements[0]) });
|
|
15058
15069
|
}
|
|
15059
15070
|
function convertAssignmentValue(expr) {
|
|
15060
15071
|
const right = convertExpression(expr.right);
|
|
@@ -15552,14 +15563,16 @@ function processStatement(stmt, bb, jumpTarget, ctx) {
|
|
|
15552
15563
|
return bb;
|
|
15553
15564
|
}
|
|
15554
15565
|
function convertExpression(node) {
|
|
15555
|
-
|
|
15566
|
+
const loc = getLoc(node);
|
|
15567
|
+
if (t.isIdentifier(node)) return { kind: "Identifier", name: node.name, loc };
|
|
15556
15568
|
if (t.isStringLiteral(node) || t.isNumericLiteral(node) || t.isBooleanLiteral(node) || t.isNullLiteral(node))
|
|
15557
|
-
return { kind: "Literal", value: node.value ?? null };
|
|
15569
|
+
return { kind: "Literal", value: node.value ?? null, loc };
|
|
15558
15570
|
if (t.isCallExpression(node)) {
|
|
15559
15571
|
const call = {
|
|
15560
15572
|
kind: "CallExpression",
|
|
15561
15573
|
callee: convertExpression(node.callee),
|
|
15562
|
-
arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean)
|
|
15574
|
+
arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
|
|
15575
|
+
loc
|
|
15563
15576
|
};
|
|
15564
15577
|
return call;
|
|
15565
15578
|
}
|
|
@@ -15574,7 +15587,8 @@ function convertExpression(node) {
|
|
|
15574
15587
|
object,
|
|
15575
15588
|
property,
|
|
15576
15589
|
computed: node.computed,
|
|
15577
|
-
optional: node.optional ?? true
|
|
15590
|
+
optional: node.optional ?? true,
|
|
15591
|
+
loc
|
|
15578
15592
|
};
|
|
15579
15593
|
return optionalMember;
|
|
15580
15594
|
}
|
|
@@ -15583,7 +15597,8 @@ function convertExpression(node) {
|
|
|
15583
15597
|
object,
|
|
15584
15598
|
property,
|
|
15585
15599
|
computed: node.computed,
|
|
15586
|
-
optional: false
|
|
15600
|
+
optional: false,
|
|
15601
|
+
loc
|
|
15587
15602
|
};
|
|
15588
15603
|
return member;
|
|
15589
15604
|
}
|
|
@@ -15592,7 +15607,8 @@ function convertExpression(node) {
|
|
|
15592
15607
|
kind: "BinaryExpression",
|
|
15593
15608
|
operator: node.operator,
|
|
15594
15609
|
left: convertExpression(node.left),
|
|
15595
|
-
right: convertExpression(node.right)
|
|
15610
|
+
right: convertExpression(node.right),
|
|
15611
|
+
loc
|
|
15596
15612
|
};
|
|
15597
15613
|
return bin;
|
|
15598
15614
|
}
|
|
@@ -15601,7 +15617,8 @@ function convertExpression(node) {
|
|
|
15601
15617
|
kind: "UnaryExpression",
|
|
15602
15618
|
operator: node.operator,
|
|
15603
15619
|
argument: convertExpression(node.argument),
|
|
15604
|
-
prefix: node.prefix
|
|
15620
|
+
prefix: node.prefix,
|
|
15621
|
+
loc
|
|
15605
15622
|
};
|
|
15606
15623
|
return un;
|
|
15607
15624
|
}
|
|
@@ -15610,7 +15627,8 @@ function convertExpression(node) {
|
|
|
15610
15627
|
kind: "LogicalExpression",
|
|
15611
15628
|
operator: node.operator,
|
|
15612
15629
|
left: convertExpression(node.left),
|
|
15613
|
-
right: convertExpression(node.right)
|
|
15630
|
+
right: convertExpression(node.right),
|
|
15631
|
+
loc
|
|
15614
15632
|
};
|
|
15615
15633
|
return log;
|
|
15616
15634
|
}
|
|
@@ -15619,7 +15637,8 @@ function convertExpression(node) {
|
|
|
15619
15637
|
kind: "ConditionalExpression",
|
|
15620
15638
|
test: convertExpression(node.test),
|
|
15621
15639
|
consequent: convertExpression(node.consequent),
|
|
15622
|
-
alternate: convertExpression(node.alternate)
|
|
15640
|
+
alternate: convertExpression(node.alternate),
|
|
15641
|
+
loc
|
|
15623
15642
|
};
|
|
15624
15643
|
return cond;
|
|
15625
15644
|
}
|
|
@@ -15631,12 +15650,14 @@ function convertExpression(node) {
|
|
|
15631
15650
|
if (t.isSpreadElement(el)) {
|
|
15632
15651
|
return {
|
|
15633
15652
|
kind: "SpreadElement",
|
|
15634
|
-
argument: convertExpression(el.argument)
|
|
15653
|
+
argument: convertExpression(el.argument),
|
|
15654
|
+
loc: getLoc(el)
|
|
15635
15655
|
};
|
|
15636
15656
|
}
|
|
15637
15657
|
if (t.isExpression(el)) return convertExpression(el);
|
|
15638
15658
|
return void 0;
|
|
15639
|
-
}).filter(Boolean)
|
|
15659
|
+
}).filter(Boolean),
|
|
15660
|
+
loc
|
|
15640
15661
|
};
|
|
15641
15662
|
return arr;
|
|
15642
15663
|
}
|
|
@@ -15647,7 +15668,8 @@ function convertExpression(node) {
|
|
|
15647
15668
|
if (t.isSpreadElement(prop)) {
|
|
15648
15669
|
return {
|
|
15649
15670
|
kind: "SpreadElement",
|
|
15650
|
-
argument: convertExpression(prop.argument)
|
|
15671
|
+
argument: convertExpression(prop.argument),
|
|
15672
|
+
loc: getLoc(prop)
|
|
15651
15673
|
};
|
|
15652
15674
|
}
|
|
15653
15675
|
if (t.isObjectMethod(prop)) {
|
|
@@ -15664,7 +15686,8 @@ function convertExpression(node) {
|
|
|
15664
15686
|
return {
|
|
15665
15687
|
kind: "Property",
|
|
15666
15688
|
key: keyExpr2,
|
|
15667
|
-
value: convertExpression(fnExpr)
|
|
15689
|
+
value: convertExpression(fnExpr),
|
|
15690
|
+
loc: getLoc(prop)
|
|
15668
15691
|
};
|
|
15669
15692
|
}
|
|
15670
15693
|
if (!t.isObjectProperty(prop) || prop.computed) return void 0;
|
|
@@ -15674,9 +15697,12 @@ function convertExpression(node) {
|
|
|
15674
15697
|
return {
|
|
15675
15698
|
kind: "Property",
|
|
15676
15699
|
key: keyExpr,
|
|
15677
|
-
value: convertExpression(prop.value)
|
|
15700
|
+
value: convertExpression(prop.value),
|
|
15701
|
+
shorthand: prop.shorthand && t.isIdentifier(prop.value),
|
|
15702
|
+
loc: getLoc(prop)
|
|
15678
15703
|
};
|
|
15679
|
-
}).filter(Boolean)
|
|
15704
|
+
}).filter(Boolean),
|
|
15705
|
+
loc
|
|
15680
15706
|
};
|
|
15681
15707
|
return obj;
|
|
15682
15708
|
}
|
|
@@ -15689,38 +15715,42 @@ function convertExpression(node) {
|
|
|
15689
15715
|
if (t.isJSXText(child)) {
|
|
15690
15716
|
const text = child.value;
|
|
15691
15717
|
if (text.trim()) {
|
|
15692
|
-
children.push({ kind: "text", value: text });
|
|
15718
|
+
children.push({ kind: "text", value: text, loc: getLoc(child) });
|
|
15693
15719
|
}
|
|
15694
15720
|
} else if (t.isJSXExpressionContainer(child)) {
|
|
15695
15721
|
if (!t.isJSXEmptyExpression(child.expression)) {
|
|
15696
15722
|
children.push({
|
|
15697
15723
|
kind: "expression",
|
|
15698
|
-
value: convertExpression(child.expression)
|
|
15724
|
+
value: convertExpression(child.expression),
|
|
15725
|
+
loc: getLoc(child)
|
|
15699
15726
|
});
|
|
15700
15727
|
}
|
|
15701
15728
|
} else if (t.isJSXElement(child)) {
|
|
15702
15729
|
children.push({
|
|
15703
15730
|
kind: "element",
|
|
15704
|
-
value: convertJSXElement(child)
|
|
15731
|
+
value: convertJSXElement(child),
|
|
15732
|
+
loc: getLoc(child)
|
|
15705
15733
|
});
|
|
15706
15734
|
} else if (t.isJSXFragment(child)) {
|
|
15707
15735
|
for (const fragChild of child.children) {
|
|
15708
15736
|
if (t.isJSXText(fragChild)) {
|
|
15709
15737
|
const text = fragChild.value;
|
|
15710
15738
|
if (text.trim()) {
|
|
15711
|
-
children.push({ kind: "text", value: text });
|
|
15739
|
+
children.push({ kind: "text", value: text, loc: getLoc(fragChild) });
|
|
15712
15740
|
}
|
|
15713
15741
|
} else if (t.isJSXExpressionContainer(fragChild)) {
|
|
15714
15742
|
if (!t.isJSXEmptyExpression(fragChild.expression)) {
|
|
15715
15743
|
children.push({
|
|
15716
15744
|
kind: "expression",
|
|
15717
|
-
value: convertExpression(fragChild.expression)
|
|
15745
|
+
value: convertExpression(fragChild.expression),
|
|
15746
|
+
loc: getLoc(fragChild)
|
|
15718
15747
|
});
|
|
15719
15748
|
}
|
|
15720
15749
|
} else if (t.isJSXElement(fragChild)) {
|
|
15721
15750
|
children.push({
|
|
15722
15751
|
kind: "element",
|
|
15723
|
-
value: convertJSXElement(fragChild)
|
|
15752
|
+
value: convertJSXElement(fragChild),
|
|
15753
|
+
loc: getLoc(fragChild)
|
|
15724
15754
|
});
|
|
15725
15755
|
}
|
|
15726
15756
|
}
|
|
@@ -15728,24 +15758,27 @@ function convertExpression(node) {
|
|
|
15728
15758
|
}
|
|
15729
15759
|
return {
|
|
15730
15760
|
kind: "JSXElement",
|
|
15731
|
-
tagName: { kind: "Identifier", name: "Fragment" },
|
|
15761
|
+
tagName: { kind: "Identifier", name: "Fragment", loc: getLoc(node) },
|
|
15732
15762
|
isComponent: true,
|
|
15733
15763
|
attributes: [],
|
|
15734
|
-
children
|
|
15764
|
+
children,
|
|
15765
|
+
loc: getLoc(node)
|
|
15735
15766
|
};
|
|
15736
15767
|
}
|
|
15737
15768
|
if (t.isArrowFunctionExpression(node)) {
|
|
15738
15769
|
if (t.isBlockStatement(node.body)) {
|
|
15739
15770
|
const nested = convertFunction(void 0, node.params, node.body.body, {
|
|
15740
15771
|
noMemo: hasNoMemoDirectiveInStatements(node.body.body),
|
|
15741
|
-
directives: node.body.directives
|
|
15772
|
+
directives: node.body.directives,
|
|
15773
|
+
loc: getLoc(node)
|
|
15742
15774
|
});
|
|
15743
15775
|
const arrow = {
|
|
15744
15776
|
kind: "ArrowFunction",
|
|
15745
15777
|
params: nested.params,
|
|
15746
15778
|
body: nested.blocks,
|
|
15747
15779
|
isExpression: false,
|
|
15748
|
-
isAsync: node.async
|
|
15780
|
+
isAsync: node.async,
|
|
15781
|
+
loc
|
|
15749
15782
|
};
|
|
15750
15783
|
return arrow;
|
|
15751
15784
|
} else {
|
|
@@ -15756,7 +15789,8 @@ function convertExpression(node) {
|
|
|
15756
15789
|
).flat(),
|
|
15757
15790
|
body: convertExpression(node.body),
|
|
15758
15791
|
isExpression: true,
|
|
15759
|
-
isAsync: node.async
|
|
15792
|
+
isAsync: node.async,
|
|
15793
|
+
loc
|
|
15760
15794
|
};
|
|
15761
15795
|
return arrow;
|
|
15762
15796
|
}
|
|
@@ -15764,14 +15798,16 @@ function convertExpression(node) {
|
|
|
15764
15798
|
if (t.isFunctionExpression(node)) {
|
|
15765
15799
|
const nested = convertFunction(void 0, node.params, node.body.body, {
|
|
15766
15800
|
noMemo: hasNoMemoDirectiveInStatements(node.body.body),
|
|
15767
|
-
directives: node.body.directives
|
|
15801
|
+
directives: node.body.directives,
|
|
15802
|
+
loc: getLoc(node)
|
|
15768
15803
|
});
|
|
15769
15804
|
const fn = {
|
|
15770
15805
|
kind: "FunctionExpression",
|
|
15771
15806
|
name: node.id?.name ?? "",
|
|
15772
15807
|
params: nested.params,
|
|
15773
15808
|
body: nested.blocks,
|
|
15774
|
-
isAsync: node.async
|
|
15809
|
+
isAsync: node.async,
|
|
15810
|
+
loc
|
|
15775
15811
|
};
|
|
15776
15812
|
return fn;
|
|
15777
15813
|
}
|
|
@@ -15780,7 +15816,8 @@ function convertExpression(node) {
|
|
|
15780
15816
|
kind: "AssignmentExpression",
|
|
15781
15817
|
operator: node.operator,
|
|
15782
15818
|
left: convertExpression(node.left),
|
|
15783
|
-
right: convertExpression(node.right)
|
|
15819
|
+
right: convertExpression(node.right),
|
|
15820
|
+
loc
|
|
15784
15821
|
};
|
|
15785
15822
|
return assign;
|
|
15786
15823
|
}
|
|
@@ -15789,7 +15826,8 @@ function convertExpression(node) {
|
|
|
15789
15826
|
kind: "UpdateExpression",
|
|
15790
15827
|
operator: node.operator,
|
|
15791
15828
|
argument: convertExpression(node.argument),
|
|
15792
|
-
prefix: node.prefix
|
|
15829
|
+
prefix: node.prefix,
|
|
15830
|
+
loc
|
|
15793
15831
|
};
|
|
15794
15832
|
return update;
|
|
15795
15833
|
}
|
|
@@ -15797,34 +15835,39 @@ function convertExpression(node) {
|
|
|
15797
15835
|
const template = {
|
|
15798
15836
|
kind: "TemplateLiteral",
|
|
15799
15837
|
quasis: node.quasis.map((q) => q.value.cooked ?? q.value.raw),
|
|
15800
|
-
expressions: node.expressions.map((e) => convertExpression(e))
|
|
15838
|
+
expressions: node.expressions.map((e) => convertExpression(e)),
|
|
15839
|
+
loc
|
|
15801
15840
|
};
|
|
15802
15841
|
return template;
|
|
15803
15842
|
}
|
|
15804
15843
|
if (t.isAwaitExpression(node)) {
|
|
15805
15844
|
return {
|
|
15806
15845
|
kind: "AwaitExpression",
|
|
15807
|
-
argument: convertExpression(node.argument)
|
|
15846
|
+
argument: convertExpression(node.argument),
|
|
15847
|
+
loc
|
|
15808
15848
|
};
|
|
15809
15849
|
}
|
|
15810
15850
|
if (t.isNewExpression(node)) {
|
|
15811
15851
|
return {
|
|
15812
15852
|
kind: "NewExpression",
|
|
15813
15853
|
callee: convertExpression(node.callee),
|
|
15814
|
-
arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean)
|
|
15854
|
+
arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
|
|
15855
|
+
loc
|
|
15815
15856
|
};
|
|
15816
15857
|
}
|
|
15817
15858
|
if (t.isSequenceExpression(node)) {
|
|
15818
15859
|
return {
|
|
15819
15860
|
kind: "SequenceExpression",
|
|
15820
|
-
expressions: node.expressions.map((e) => convertExpression(e))
|
|
15861
|
+
expressions: node.expressions.map((e) => convertExpression(e)),
|
|
15862
|
+
loc
|
|
15821
15863
|
};
|
|
15822
15864
|
}
|
|
15823
15865
|
if (t.isYieldExpression(node)) {
|
|
15824
15866
|
return {
|
|
15825
15867
|
kind: "YieldExpression",
|
|
15826
15868
|
argument: node.argument ? convertExpression(node.argument) : null,
|
|
15827
|
-
delegate: node.delegate
|
|
15869
|
+
delegate: node.delegate,
|
|
15870
|
+
loc
|
|
15828
15871
|
};
|
|
15829
15872
|
}
|
|
15830
15873
|
if (t.isOptionalCallExpression(node)) {
|
|
@@ -15832,7 +15875,8 @@ function convertExpression(node) {
|
|
|
15832
15875
|
kind: "OptionalCallExpression",
|
|
15833
15876
|
callee: convertExpression(node.callee),
|
|
15834
15877
|
arguments: node.arguments.map((arg) => t.isExpression(arg) ? convertExpression(arg) : void 0).filter(Boolean),
|
|
15835
|
-
optional: node.optional
|
|
15878
|
+
optional: node.optional,
|
|
15879
|
+
loc
|
|
15836
15880
|
};
|
|
15837
15881
|
}
|
|
15838
15882
|
if (t.isTaggedTemplateExpression(node)) {
|
|
@@ -15844,8 +15888,10 @@ function convertExpression(node) {
|
|
|
15844
15888
|
quasis: node.quasi.quasis.map((q) => q.value.cooked ?? q.value.raw),
|
|
15845
15889
|
expressions: node.quasi.expressions.map(
|
|
15846
15890
|
(e) => convertExpression(e)
|
|
15847
|
-
)
|
|
15848
|
-
|
|
15891
|
+
),
|
|
15892
|
+
loc: getLoc(node.quasi)
|
|
15893
|
+
},
|
|
15894
|
+
loc
|
|
15849
15895
|
};
|
|
15850
15896
|
}
|
|
15851
15897
|
if (t.isClassExpression(node)) {
|
|
@@ -15853,17 +15899,18 @@ function convertExpression(node) {
|
|
|
15853
15899
|
kind: "ClassExpression",
|
|
15854
15900
|
name: node.id?.name,
|
|
15855
15901
|
superClass: node.superClass ? convertExpression(node.superClass) : void 0,
|
|
15856
|
-
body: node.body.body
|
|
15902
|
+
body: node.body.body,
|
|
15857
15903
|
// Store as Babel AST for now
|
|
15904
|
+
loc
|
|
15858
15905
|
};
|
|
15859
15906
|
}
|
|
15860
15907
|
if (t.isThisExpression(node)) {
|
|
15861
|
-
return { kind: "ThisExpression" };
|
|
15908
|
+
return { kind: "ThisExpression", loc };
|
|
15862
15909
|
}
|
|
15863
15910
|
if (t.isSuper(node)) {
|
|
15864
|
-
return { kind: "SuperExpression" };
|
|
15911
|
+
return { kind: "SuperExpression", loc };
|
|
15865
15912
|
}
|
|
15866
|
-
const fallback = { kind: "Literal", value: void 0 };
|
|
15913
|
+
const fallback = { kind: "Literal", value: void 0, loc };
|
|
15867
15914
|
return fallback;
|
|
15868
15915
|
}
|
|
15869
15916
|
function convertJSXElement(node) {
|
|
@@ -15874,7 +15921,7 @@ function convertJSXElement(node) {
|
|
|
15874
15921
|
const name = opening.name.name;
|
|
15875
15922
|
const firstChar = name[0];
|
|
15876
15923
|
if (firstChar && firstChar === firstChar.toUpperCase()) {
|
|
15877
|
-
tagName = { kind: "Identifier", name };
|
|
15924
|
+
tagName = { kind: "Identifier", name, loc: getLoc(opening.name) };
|
|
15878
15925
|
isComponent = true;
|
|
15879
15926
|
} else {
|
|
15880
15927
|
tagName = name;
|
|
@@ -15892,20 +15939,22 @@ function convertJSXElement(node) {
|
|
|
15892
15939
|
name: "",
|
|
15893
15940
|
value: null,
|
|
15894
15941
|
isSpread: true,
|
|
15895
|
-
spreadExpr: convertExpression(attr.argument)
|
|
15942
|
+
spreadExpr: convertExpression(attr.argument),
|
|
15943
|
+
loc: getLoc(attr)
|
|
15896
15944
|
});
|
|
15897
15945
|
} else if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
|
|
15898
15946
|
let value = null;
|
|
15899
15947
|
if (attr.value) {
|
|
15900
15948
|
if (t.isStringLiteral(attr.value)) {
|
|
15901
|
-
value = { kind: "Literal", value: attr.value.value };
|
|
15949
|
+
value = { kind: "Literal", value: attr.value.value, loc: getLoc(attr.value) };
|
|
15902
15950
|
} else if (t.isJSXExpressionContainer(attr.value) && !t.isJSXEmptyExpression(attr.value.expression)) {
|
|
15903
15951
|
value = convertExpression(attr.value.expression);
|
|
15904
15952
|
}
|
|
15905
15953
|
}
|
|
15906
15954
|
attributes.push({
|
|
15907
15955
|
name: attr.name.name,
|
|
15908
|
-
value
|
|
15956
|
+
value,
|
|
15957
|
+
loc: getLoc(attr)
|
|
15909
15958
|
});
|
|
15910
15959
|
}
|
|
15911
15960
|
}
|
|
@@ -15914,38 +15963,42 @@ function convertJSXElement(node) {
|
|
|
15914
15963
|
if (t.isJSXText(child)) {
|
|
15915
15964
|
const text = child.value;
|
|
15916
15965
|
if (text.trim()) {
|
|
15917
|
-
children.push({ kind: "text", value: text });
|
|
15966
|
+
children.push({ kind: "text", value: text, loc: getLoc(child) });
|
|
15918
15967
|
}
|
|
15919
15968
|
} else if (t.isJSXExpressionContainer(child)) {
|
|
15920
15969
|
if (!t.isJSXEmptyExpression(child.expression)) {
|
|
15921
15970
|
children.push({
|
|
15922
15971
|
kind: "expression",
|
|
15923
|
-
value: convertExpression(child.expression)
|
|
15972
|
+
value: convertExpression(child.expression),
|
|
15973
|
+
loc: getLoc(child)
|
|
15924
15974
|
});
|
|
15925
15975
|
}
|
|
15926
15976
|
} else if (t.isJSXElement(child)) {
|
|
15927
15977
|
children.push({
|
|
15928
15978
|
kind: "element",
|
|
15929
|
-
value: convertJSXElement(child)
|
|
15979
|
+
value: convertJSXElement(child),
|
|
15980
|
+
loc: getLoc(child)
|
|
15930
15981
|
});
|
|
15931
15982
|
} else if (t.isJSXFragment(child)) {
|
|
15932
15983
|
for (const fragChild of child.children) {
|
|
15933
15984
|
if (t.isJSXText(fragChild)) {
|
|
15934
15985
|
const text = fragChild.value;
|
|
15935
15986
|
if (text.trim()) {
|
|
15936
|
-
children.push({ kind: "text", value: text });
|
|
15987
|
+
children.push({ kind: "text", value: text, loc: getLoc(fragChild) });
|
|
15937
15988
|
}
|
|
15938
15989
|
} else if (t.isJSXExpressionContainer(fragChild)) {
|
|
15939
15990
|
if (!t.isJSXEmptyExpression(fragChild.expression)) {
|
|
15940
15991
|
children.push({
|
|
15941
15992
|
kind: "expression",
|
|
15942
|
-
value: convertExpression(fragChild.expression)
|
|
15993
|
+
value: convertExpression(fragChild.expression),
|
|
15994
|
+
loc: getLoc(fragChild)
|
|
15943
15995
|
});
|
|
15944
15996
|
}
|
|
15945
15997
|
} else if (t.isJSXElement(fragChild)) {
|
|
15946
15998
|
children.push({
|
|
15947
15999
|
kind: "element",
|
|
15948
|
-
value: convertJSXElement(fragChild)
|
|
16000
|
+
value: convertJSXElement(fragChild),
|
|
16001
|
+
loc: getLoc(fragChild)
|
|
15949
16002
|
});
|
|
15950
16003
|
}
|
|
15951
16004
|
}
|
|
@@ -15956,21 +16009,27 @@ function convertJSXElement(node) {
|
|
|
15956
16009
|
tagName,
|
|
15957
16010
|
isComponent,
|
|
15958
16011
|
attributes,
|
|
15959
|
-
children
|
|
16012
|
+
children,
|
|
16013
|
+
loc: getLoc(node)
|
|
15960
16014
|
};
|
|
15961
16015
|
}
|
|
15962
16016
|
function convertJSXMemberExpr(node) {
|
|
15963
16017
|
let object;
|
|
15964
16018
|
if (t.isJSXIdentifier(node.object)) {
|
|
15965
|
-
object = { kind: "Identifier", name: node.object.name };
|
|
16019
|
+
object = { kind: "Identifier", name: node.object.name, loc: getLoc(node.object) };
|
|
15966
16020
|
} else {
|
|
15967
16021
|
object = convertJSXMemberExpr(node.object);
|
|
15968
16022
|
}
|
|
15969
16023
|
return {
|
|
15970
16024
|
kind: "MemberExpression",
|
|
15971
16025
|
object,
|
|
15972
|
-
property: {
|
|
15973
|
-
|
|
16026
|
+
property: {
|
|
16027
|
+
kind: "Identifier",
|
|
16028
|
+
name: node.property.name,
|
|
16029
|
+
loc: getLoc(node.property)
|
|
16030
|
+
},
|
|
16031
|
+
computed: false,
|
|
16032
|
+
loc: getLoc(node)
|
|
15974
16033
|
};
|
|
15975
16034
|
}
|
|
15976
16035
|
|
|
@@ -18284,7 +18343,8 @@ function lowerNodeWithRegionContext(node, t2, ctx, declaredVars, regionCtx) {
|
|
|
18284
18343
|
t2.blockStatement(conseqStmts),
|
|
18285
18344
|
altStmts ? t2.blockStatement(altStmts) : null
|
|
18286
18345
|
);
|
|
18287
|
-
const
|
|
18346
|
+
const inNonReactiveScope = !!(ctx.nonReactiveScopeDepth && ctx.nonReactiveScopeDepth > 0);
|
|
18347
|
+
const shouldWrapEffect = ctx.wrapTrackedExpressions !== false && !ctx.inRegionMemo && !inNonReactiveScope && expressionUsesTracked(node.test, ctx) && !statementHasEarlyExit(ifStmt, t2);
|
|
18288
18348
|
if (shouldWrapEffect) {
|
|
18289
18349
|
ctx.helpersUsed.add("useEffect");
|
|
18290
18350
|
ctx.needsCtx = true;
|
|
@@ -18512,31 +18572,53 @@ function lowerStructuredNodeForRegion(node, region, t2, ctx, declaredVars, regio
|
|
|
18512
18572
|
return stmt ? [stmt] : [];
|
|
18513
18573
|
}
|
|
18514
18574
|
case "if": {
|
|
18515
|
-
const
|
|
18516
|
-
|
|
18517
|
-
|
|
18518
|
-
|
|
18519
|
-
|
|
18520
|
-
|
|
18521
|
-
|
|
18522
|
-
|
|
18523
|
-
|
|
18524
|
-
|
|
18525
|
-
|
|
18526
|
-
|
|
18527
|
-
|
|
18528
|
-
|
|
18529
|
-
|
|
18530
|
-
|
|
18531
|
-
|
|
18532
|
-
|
|
18575
|
+
const inNonReactiveScope = !!(ctx.nonReactiveScopeDepth && ctx.nonReactiveScopeDepth > 0);
|
|
18576
|
+
const baseShouldWrapEffect = ctx.wrapTrackedExpressions !== false && !ctx.inRegionMemo && !inNonReactiveScope && expressionUsesTracked(node.test, ctx);
|
|
18577
|
+
const lowerChild = (child, forceNonReactive) => {
|
|
18578
|
+
if (!child) return [];
|
|
18579
|
+
if (!forceNonReactive) {
|
|
18580
|
+
return lowerStructuredNodeForRegion(
|
|
18581
|
+
child,
|
|
18582
|
+
region,
|
|
18583
|
+
t2,
|
|
18584
|
+
ctx,
|
|
18585
|
+
declaredVars,
|
|
18586
|
+
regionCtx,
|
|
18587
|
+
skipInstructions
|
|
18588
|
+
);
|
|
18589
|
+
}
|
|
18590
|
+
const prevDepth = ctx.nonReactiveScopeDepth ?? 0;
|
|
18591
|
+
ctx.nonReactiveScopeDepth = prevDepth + 1;
|
|
18592
|
+
try {
|
|
18593
|
+
return lowerStructuredNodeForRegion(
|
|
18594
|
+
child,
|
|
18595
|
+
region,
|
|
18596
|
+
t2,
|
|
18597
|
+
ctx,
|
|
18598
|
+
declaredVars,
|
|
18599
|
+
regionCtx,
|
|
18600
|
+
skipInstructions
|
|
18601
|
+
);
|
|
18602
|
+
} finally {
|
|
18603
|
+
ctx.nonReactiveScopeDepth = prevDepth;
|
|
18604
|
+
}
|
|
18605
|
+
};
|
|
18606
|
+
let consequent = lowerChild(node.consequent, baseShouldWrapEffect);
|
|
18607
|
+
let alternate = node.alternate ? lowerChild(node.alternate, baseShouldWrapEffect) : [];
|
|
18533
18608
|
if (consequent.length === 0 && alternate.length === 0) return [];
|
|
18534
|
-
const
|
|
18609
|
+
const buildIfStmt = (cons, alt) => t2.ifStatement(
|
|
18535
18610
|
lowerExpressionWithDeSSA(node.test, ctx),
|
|
18536
|
-
t2.blockStatement(
|
|
18537
|
-
|
|
18611
|
+
t2.blockStatement(cons),
|
|
18612
|
+
alt.length > 0 ? t2.blockStatement(alt) : null
|
|
18538
18613
|
);
|
|
18539
|
-
|
|
18614
|
+
let ifStmt = buildIfStmt(consequent, alternate);
|
|
18615
|
+
const shouldWrapEffect = baseShouldWrapEffect && !statementHasEarlyExit(ifStmt, t2);
|
|
18616
|
+
if (!shouldWrapEffect && baseShouldWrapEffect) {
|
|
18617
|
+
consequent = lowerChild(node.consequent, false);
|
|
18618
|
+
alternate = node.alternate ? lowerChild(node.alternate, false) : [];
|
|
18619
|
+
if (consequent.length === 0 && alternate.length === 0) return [];
|
|
18620
|
+
ifStmt = buildIfStmt(consequent, alternate);
|
|
18621
|
+
}
|
|
18540
18622
|
if (shouldWrapEffect) {
|
|
18541
18623
|
ctx.helpersUsed.add("useEffect");
|
|
18542
18624
|
ctx.needsCtx = true;
|
|
@@ -18928,11 +19010,17 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
18928
19010
|
if (uniqueOutputNames.length === 0) {
|
|
18929
19011
|
ctx.helpersUsed.add("useEffect");
|
|
18930
19012
|
ctx.needsCtx = true;
|
|
18931
|
-
const
|
|
19013
|
+
const effectCallArgs = [
|
|
18932
19014
|
t2.identifier("__fictCtx"),
|
|
18933
|
-
t2.arrowFunctionExpression([], t2.blockStatement(bodyStatements))
|
|
18934
|
-
|
|
18935
|
-
|
|
19015
|
+
t2.arrowFunctionExpression([], t2.blockStatement(bodyStatements))
|
|
19016
|
+
];
|
|
19017
|
+
{
|
|
19018
|
+
const slot = reserveHookSlot(ctx);
|
|
19019
|
+
if (slot >= 0) {
|
|
19020
|
+
effectCallArgs.push(t2.numericLiteral(slot));
|
|
19021
|
+
}
|
|
19022
|
+
}
|
|
19023
|
+
const effectCall = t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), effectCallArgs);
|
|
18936
19024
|
statements.push(t2.expressionStatement(effectCall));
|
|
18937
19025
|
} else {
|
|
18938
19026
|
ctx.helpersUsed.add("useMemo");
|
|
@@ -18965,11 +19053,15 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
18965
19053
|
};
|
|
18966
19054
|
const returnObj = t2.objectExpression(uniqueOutputNames.map((name) => buildOutputProperty(name)));
|
|
18967
19055
|
const memoBody = t2.blockStatement([...bodyStatements, t2.returnStatement(returnObj)]);
|
|
18968
|
-
const
|
|
19056
|
+
const slot = reserveHookSlot(ctx);
|
|
19057
|
+
const memoArgs = [
|
|
18969
19058
|
t2.identifier("__fictCtx"),
|
|
18970
|
-
t2.arrowFunctionExpression([], memoBody)
|
|
18971
|
-
|
|
18972
|
-
|
|
19059
|
+
t2.arrowFunctionExpression([], memoBody)
|
|
19060
|
+
];
|
|
19061
|
+
if (slot >= 0) {
|
|
19062
|
+
memoArgs.push(t2.numericLiteral(slot));
|
|
19063
|
+
}
|
|
19064
|
+
const memoCall = t2.callExpression(t2.identifier(RUNTIME_ALIASES.useMemo), memoArgs);
|
|
18973
19065
|
const regionVarName = `__region_${region.id}`;
|
|
18974
19066
|
statements.push(
|
|
18975
19067
|
t2.variableDeclaration("const", [t2.variableDeclarator(t2.identifier(regionVarName), memoCall)])
|
|
@@ -19026,7 +19118,10 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
19026
19118
|
t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), [
|
|
19027
19119
|
t2.identifier("__fictCtx"),
|
|
19028
19120
|
t2.arrowFunctionExpression([], effectBody),
|
|
19029
|
-
|
|
19121
|
+
(() => {
|
|
19122
|
+
const slot2 = reserveHookSlot(ctx);
|
|
19123
|
+
return slot2 >= 0 ? t2.numericLiteral(slot2) : t2.identifier("undefined");
|
|
19124
|
+
})()
|
|
19030
19125
|
])
|
|
19031
19126
|
)
|
|
19032
19127
|
);
|
|
@@ -19244,11 +19339,15 @@ function generateLazyConditionalMemo(region, orderedOutputs, bodyStatements, con
|
|
|
19244
19339
|
ctx.helpersUsed.add("useMemo");
|
|
19245
19340
|
ctx.needsCtx = true;
|
|
19246
19341
|
const regionVarName = `__region_${region.id}`;
|
|
19247
|
-
const
|
|
19342
|
+
const slotForMemo = reserveHookSlot(ctx);
|
|
19343
|
+
const memoArgs = [
|
|
19248
19344
|
t2.identifier("__fictCtx"),
|
|
19249
|
-
t2.arrowFunctionExpression([], t2.blockStatement(memoBody))
|
|
19250
|
-
|
|
19251
|
-
|
|
19345
|
+
t2.arrowFunctionExpression([], t2.blockStatement(memoBody))
|
|
19346
|
+
];
|
|
19347
|
+
if (slotForMemo >= 0) {
|
|
19348
|
+
memoArgs.push(t2.numericLiteral(slotForMemo));
|
|
19349
|
+
}
|
|
19350
|
+
const memoCall = t2.callExpression(t2.identifier("__fictUseMemo"), memoArgs);
|
|
19252
19351
|
statements.push(
|
|
19253
19352
|
t2.variableDeclaration("const", [t2.variableDeclarator(t2.identifier(regionVarName), memoCall)])
|
|
19254
19353
|
);
|
|
@@ -19270,6 +19369,9 @@ function generateLazyConditionalMemo(region, orderedOutputs, bodyStatements, con
|
|
|
19270
19369
|
return statements;
|
|
19271
19370
|
}
|
|
19272
19371
|
function reserveHookSlot(ctx) {
|
|
19372
|
+
if (ctx.dynamicHookSlotDepth && ctx.dynamicHookSlotDepth > 0) {
|
|
19373
|
+
return -1;
|
|
19374
|
+
}
|
|
19273
19375
|
const slot = ctx.nextHookSlot ?? 0;
|
|
19274
19376
|
ctx.nextHookSlot = slot + 1;
|
|
19275
19377
|
return slot;
|
|
@@ -19340,7 +19442,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19340
19442
|
t2.arrowFunctionExpression([], expr)
|
|
19341
19443
|
];
|
|
19342
19444
|
if (inRegionMemo) {
|
|
19343
|
-
|
|
19445
|
+
const slot = reserveHookSlot(ctx);
|
|
19446
|
+
if (slot >= 0) {
|
|
19447
|
+
args.push(t2.numericLiteral(slot));
|
|
19448
|
+
}
|
|
19344
19449
|
}
|
|
19345
19450
|
ctx.helpersUsed.add("useMemo");
|
|
19346
19451
|
ctx.needsCtx = true;
|
|
@@ -19540,7 +19645,8 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19540
19645
|
(dep) => ctx.trackedVars.has(deSSAVarName(dep))
|
|
19541
19646
|
);
|
|
19542
19647
|
const usesTracked = expressionUsesTracked(instr.value, ctx);
|
|
19543
|
-
const
|
|
19648
|
+
const inNonReactiveScope = !!(ctx.nonReactiveScopeDepth && ctx.nonReactiveScopeDepth > 0);
|
|
19649
|
+
const shouldWrapExpr = ctx.wrapTrackedExpressions !== false && !inNonReactiveScope && (usesTracked || hasTrackedControlDep);
|
|
19544
19650
|
if (shouldWrapExpr) {
|
|
19545
19651
|
ctx.helpersUsed.add("useEffect");
|
|
19546
19652
|
ctx.needsCtx = true;
|
|
@@ -19855,6 +19961,17 @@ function deSSAJSXChild(child, t2) {
|
|
|
19855
19961
|
// src/ir/codegen.ts
|
|
19856
19962
|
var HOOK_SLOT_BASE = 1e3;
|
|
19857
19963
|
var HOOK_NAME_PREFIX = "use";
|
|
19964
|
+
var cloneLoc = (loc) => loc === void 0 ? void 0 : loc === null ? null : {
|
|
19965
|
+
start: { ...loc.start },
|
|
19966
|
+
end: { ...loc.end },
|
|
19967
|
+
filename: loc.filename,
|
|
19968
|
+
identifierName: loc.identifierName
|
|
19969
|
+
};
|
|
19970
|
+
function setNodeLoc(node, loc) {
|
|
19971
|
+
if (loc === void 0) return node;
|
|
19972
|
+
node.loc = cloneLoc(loc) ?? null;
|
|
19973
|
+
return node;
|
|
19974
|
+
}
|
|
19858
19975
|
function isHookName(name) {
|
|
19859
19976
|
return !!name && name.startsWith(HOOK_NAME_PREFIX);
|
|
19860
19977
|
}
|
|
@@ -19888,13 +20005,22 @@ function applyRegionToContext(ctx, region) {
|
|
|
19888
20005
|
return prevRegion;
|
|
19889
20006
|
}
|
|
19890
20007
|
function reserveHookSlot2(ctx) {
|
|
20008
|
+
if (ctx.dynamicHookSlotDepth && ctx.dynamicHookSlotDepth > 0) {
|
|
20009
|
+
return -1;
|
|
20010
|
+
}
|
|
19891
20011
|
const slot = ctx.nextHookSlot ?? HOOK_SLOT_BASE;
|
|
19892
20012
|
ctx.nextHookSlot = slot + 1;
|
|
19893
20013
|
return slot;
|
|
19894
20014
|
}
|
|
19895
20015
|
function expressionContainsJSX(expr) {
|
|
20016
|
+
if (Array.isArray(expr)) {
|
|
20017
|
+
return expr.some((item) => expressionContainsJSX(item));
|
|
20018
|
+
}
|
|
19896
20019
|
if (!expr || typeof expr !== "object") return false;
|
|
19897
20020
|
if (expr.kind === "JSXElement") return true;
|
|
20021
|
+
if (Array.isArray(expr.instructions)) {
|
|
20022
|
+
return expr.instructions.some((i) => expressionContainsJSX(i?.value ?? i));
|
|
20023
|
+
}
|
|
19898
20024
|
switch (expr.kind) {
|
|
19899
20025
|
case "CallExpression":
|
|
19900
20026
|
if (expressionContainsJSX(expr.callee)) return true;
|
|
@@ -19907,10 +20033,29 @@ function expressionContainsJSX(expr) {
|
|
|
19907
20033
|
return expressionContainsJSX(expr.test) || expressionContainsJSX(expr.consequent) || expressionContainsJSX(expr.alternate);
|
|
19908
20034
|
case "ArrowFunction":
|
|
19909
20035
|
return expressionContainsJSX(expr.body);
|
|
20036
|
+
case "FunctionExpression":
|
|
20037
|
+
if (Array.isArray(expr.body)) {
|
|
20038
|
+
return expr.body.some(
|
|
20039
|
+
(block) => block.instructions?.some((i) => expressionContainsJSX(i.value))
|
|
20040
|
+
);
|
|
20041
|
+
}
|
|
20042
|
+
return false;
|
|
19910
20043
|
default:
|
|
19911
20044
|
return false;
|
|
19912
20045
|
}
|
|
19913
20046
|
}
|
|
20047
|
+
function withNoMemoAndDynamicHooks(ctx, fn) {
|
|
20048
|
+
const prevNoMemo = ctx.noMemo;
|
|
20049
|
+
const prevDynamic = ctx.dynamicHookSlotDepth ?? 0;
|
|
20050
|
+
ctx.noMemo = true;
|
|
20051
|
+
ctx.dynamicHookSlotDepth = prevDynamic + 1;
|
|
20052
|
+
try {
|
|
20053
|
+
return fn();
|
|
20054
|
+
} finally {
|
|
20055
|
+
ctx.noMemo = prevNoMemo;
|
|
20056
|
+
ctx.dynamicHookSlotDepth = prevDynamic;
|
|
20057
|
+
}
|
|
20058
|
+
}
|
|
19914
20059
|
function functionContainsJSX(fn) {
|
|
19915
20060
|
for (const block of fn.blocks) {
|
|
19916
20061
|
for (const instr of block.instructions) {
|
|
@@ -21009,18 +21154,25 @@ function lowerTrackedExpression(expr, ctx) {
|
|
|
21009
21154
|
}
|
|
21010
21155
|
function lowerInstruction(instr, ctx) {
|
|
21011
21156
|
const { t: t2 } = ctx;
|
|
21157
|
+
const applyLoc = (stmt) => {
|
|
21158
|
+
if (!stmt) return stmt;
|
|
21159
|
+
const baseLoc = instr.loc ?? (instr.kind === "Assign" || instr.kind === "Expression" ? instr.value.loc : void 0);
|
|
21160
|
+
return setNodeLoc(stmt, baseLoc);
|
|
21161
|
+
};
|
|
21012
21162
|
if (instr.kind === "Assign") {
|
|
21013
21163
|
const baseName2 = deSSAVarName(instr.target.name);
|
|
21014
21164
|
const isFunctionDecl = instr.value.kind === "FunctionExpression" && (instr.declarationKind === "function" || !instr.declarationKind && instr.value.name === baseName2);
|
|
21015
21165
|
if (isFunctionDecl) {
|
|
21016
21166
|
const loweredFn = lowerExpression(instr.value, ctx);
|
|
21017
21167
|
if (t2.isFunctionExpression(loweredFn)) {
|
|
21018
|
-
return
|
|
21019
|
-
t2.
|
|
21020
|
-
|
|
21021
|
-
|
|
21022
|
-
|
|
21023
|
-
|
|
21168
|
+
return applyLoc(
|
|
21169
|
+
t2.functionDeclaration(
|
|
21170
|
+
t2.identifier(baseName2),
|
|
21171
|
+
loweredFn.params,
|
|
21172
|
+
loweredFn.body,
|
|
21173
|
+
loweredFn.generator ?? false,
|
|
21174
|
+
loweredFn.async ?? false
|
|
21175
|
+
)
|
|
21024
21176
|
);
|
|
21025
21177
|
}
|
|
21026
21178
|
}
|
|
@@ -21035,12 +21187,16 @@ function lowerInstruction(instr, ctx) {
|
|
|
21035
21187
|
ctx.memoVars?.add(baseName2);
|
|
21036
21188
|
}
|
|
21037
21189
|
if (declKind) {
|
|
21038
|
-
return
|
|
21039
|
-
t2.
|
|
21040
|
-
|
|
21190
|
+
return applyLoc(
|
|
21191
|
+
t2.variableDeclaration(declKind, [
|
|
21192
|
+
t2.variableDeclarator(t2.identifier(baseName2), hookMember.member)
|
|
21193
|
+
])
|
|
21194
|
+
);
|
|
21041
21195
|
}
|
|
21042
|
-
return
|
|
21043
|
-
t2.
|
|
21196
|
+
return applyLoc(
|
|
21197
|
+
t2.expressionStatement(
|
|
21198
|
+
t2.assignmentExpression("=", t2.identifier(baseName2), hookMember.member)
|
|
21199
|
+
)
|
|
21044
21200
|
);
|
|
21045
21201
|
}
|
|
21046
21202
|
if (instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && isHookName(instr.value.callee.name)) {
|
|
@@ -21054,16 +21210,24 @@ function lowerInstruction(instr, ctx) {
|
|
|
21054
21210
|
}
|
|
21055
21211
|
}
|
|
21056
21212
|
if (ctx.signalVars?.has(baseName2)) {
|
|
21057
|
-
return
|
|
21058
|
-
t2.
|
|
21213
|
+
return applyLoc(
|
|
21214
|
+
t2.expressionStatement(
|
|
21215
|
+
t2.callExpression(t2.identifier(baseName2), [lowerTrackedExpression(instr.value, ctx)])
|
|
21216
|
+
)
|
|
21059
21217
|
);
|
|
21060
21218
|
}
|
|
21061
|
-
return
|
|
21062
|
-
t2.
|
|
21219
|
+
return applyLoc(
|
|
21220
|
+
t2.expressionStatement(
|
|
21221
|
+
t2.assignmentExpression(
|
|
21222
|
+
"=",
|
|
21223
|
+
t2.identifier(baseName2),
|
|
21224
|
+
lowerTrackedExpression(instr.value, ctx)
|
|
21225
|
+
)
|
|
21226
|
+
)
|
|
21063
21227
|
);
|
|
21064
21228
|
}
|
|
21065
21229
|
if (instr.kind === "Expression") {
|
|
21066
|
-
return t2.expressionStatement(lowerTrackedExpression(instr.value, ctx));
|
|
21230
|
+
return applyLoc(t2.expressionStatement(lowerTrackedExpression(instr.value, ctx)));
|
|
21067
21231
|
}
|
|
21068
21232
|
if (instr.kind === "Phi") {
|
|
21069
21233
|
return null;
|
|
@@ -21072,6 +21236,9 @@ function lowerInstruction(instr, ctx) {
|
|
|
21072
21236
|
}
|
|
21073
21237
|
function lowerTerminator(block, ctx) {
|
|
21074
21238
|
const { t: t2 } = ctx;
|
|
21239
|
+
const baseLoc = block.terminator.loc ?? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21240
|
+
block.terminator.argument?.loc;
|
|
21241
|
+
const applyLoc = (stmts) => stmts.map((stmt) => setNodeLoc(stmt, baseLoc));
|
|
21075
21242
|
switch (block.terminator.kind) {
|
|
21076
21243
|
case "Return": {
|
|
21077
21244
|
const prevRegion = ctx.currentRegion;
|
|
@@ -21084,14 +21251,14 @@ function lowerTerminator(block, ctx) {
|
|
|
21084
21251
|
}
|
|
21085
21252
|
ctx.inReturn = false;
|
|
21086
21253
|
ctx.currentRegion = prevRegion;
|
|
21087
|
-
return [t2.returnStatement(retExpr)];
|
|
21254
|
+
return applyLoc([t2.returnStatement(retExpr)]);
|
|
21088
21255
|
}
|
|
21089
21256
|
case "Throw":
|
|
21090
|
-
return [t2.throwStatement(lowerTrackedExpression(block.terminator.argument, ctx))];
|
|
21257
|
+
return applyLoc([t2.throwStatement(lowerTrackedExpression(block.terminator.argument, ctx))]);
|
|
21091
21258
|
case "Jump":
|
|
21092
|
-
return [t2.expressionStatement(t2.stringLiteral(`jump ${block.terminator.target}`))];
|
|
21259
|
+
return applyLoc([t2.expressionStatement(t2.stringLiteral(`jump ${block.terminator.target}`))]);
|
|
21093
21260
|
case "Branch":
|
|
21094
|
-
return [
|
|
21261
|
+
return applyLoc([
|
|
21095
21262
|
t2.ifStatement(
|
|
21096
21263
|
lowerTrackedExpression(block.terminator.test, ctx),
|
|
21097
21264
|
t2.blockStatement([
|
|
@@ -21101,9 +21268,9 @@ function lowerTerminator(block, ctx) {
|
|
|
21101
21268
|
t2.expressionStatement(t2.stringLiteral(`goto ${block.terminator.alternate}`))
|
|
21102
21269
|
])
|
|
21103
21270
|
)
|
|
21104
|
-
];
|
|
21271
|
+
]);
|
|
21105
21272
|
case "Switch":
|
|
21106
|
-
return [
|
|
21273
|
+
return applyLoc([
|
|
21107
21274
|
t2.switchStatement(
|
|
21108
21275
|
lowerTrackedExpression(block.terminator.discriminant, ctx),
|
|
21109
21276
|
block.terminator.cases.map(
|
|
@@ -21112,30 +21279,30 @@ function lowerTerminator(block, ctx) {
|
|
|
21112
21279
|
])
|
|
21113
21280
|
)
|
|
21114
21281
|
)
|
|
21115
|
-
];
|
|
21282
|
+
]);
|
|
21116
21283
|
case "ForOf": {
|
|
21117
21284
|
const term = block.terminator;
|
|
21118
21285
|
const varKind = term.variableKind ?? "const";
|
|
21119
21286
|
const leftPattern = term.pattern ? term.pattern : t2.identifier(term.variable);
|
|
21120
|
-
return [
|
|
21287
|
+
return applyLoc([
|
|
21121
21288
|
t2.forOfStatement(
|
|
21122
21289
|
t2.variableDeclaration(varKind, [t2.variableDeclarator(leftPattern)]),
|
|
21123
21290
|
lowerExpression(term.iterable, ctx),
|
|
21124
21291
|
t2.blockStatement([t2.expressionStatement(t2.stringLiteral(`body ${term.body}`))])
|
|
21125
21292
|
)
|
|
21126
|
-
];
|
|
21293
|
+
]);
|
|
21127
21294
|
}
|
|
21128
21295
|
case "ForIn": {
|
|
21129
21296
|
const term = block.terminator;
|
|
21130
21297
|
const varKind = term.variableKind ?? "const";
|
|
21131
21298
|
const leftPattern = term.pattern ? term.pattern : t2.identifier(term.variable);
|
|
21132
|
-
return [
|
|
21299
|
+
return applyLoc([
|
|
21133
21300
|
t2.forInStatement(
|
|
21134
21301
|
t2.variableDeclaration(varKind, [t2.variableDeclarator(leftPattern)]),
|
|
21135
21302
|
lowerExpression(term.object, ctx),
|
|
21136
21303
|
t2.blockStatement([t2.expressionStatement(t2.stringLiteral(`body ${term.body}`))])
|
|
21137
21304
|
)
|
|
21138
|
-
];
|
|
21305
|
+
]);
|
|
21139
21306
|
}
|
|
21140
21307
|
case "Try": {
|
|
21141
21308
|
const term = block.terminator;
|
|
@@ -21151,20 +21318,20 @@ function lowerTerminator(block, ctx) {
|
|
|
21151
21318
|
const finallyBlock = term.finallyBlock !== void 0 ? t2.blockStatement([
|
|
21152
21319
|
t2.expressionStatement(t2.stringLiteral(`finally ${term.finallyBlock}`))
|
|
21153
21320
|
]) : null;
|
|
21154
|
-
return [t2.tryStatement(tryBlock, catchClause, finallyBlock)];
|
|
21321
|
+
return applyLoc([t2.tryStatement(tryBlock, catchClause, finallyBlock)]);
|
|
21155
21322
|
}
|
|
21156
21323
|
case "Unreachable":
|
|
21157
|
-
return [];
|
|
21324
|
+
return applyLoc([]);
|
|
21158
21325
|
case "Break":
|
|
21159
|
-
return [
|
|
21326
|
+
return applyLoc([
|
|
21160
21327
|
t2.breakStatement(block.terminator.label ? t2.identifier(block.terminator.label) : null)
|
|
21161
|
-
];
|
|
21328
|
+
]);
|
|
21162
21329
|
case "Continue":
|
|
21163
|
-
return [
|
|
21330
|
+
return applyLoc([
|
|
21164
21331
|
t2.continueStatement(block.terminator.label ? t2.identifier(block.terminator.label) : null)
|
|
21165
|
-
];
|
|
21332
|
+
]);
|
|
21166
21333
|
default:
|
|
21167
|
-
return [];
|
|
21334
|
+
return applyLoc([]);
|
|
21168
21335
|
}
|
|
21169
21336
|
}
|
|
21170
21337
|
function attachHelperImports(ctx, body, t2) {
|
|
@@ -21303,12 +21470,12 @@ function lowerExpression(expr, ctx, isAssigned = false) {
|
|
|
21303
21470
|
}
|
|
21304
21471
|
ctx.expressionDepth = depth;
|
|
21305
21472
|
try {
|
|
21306
|
-
return lowerExpressionImpl(expr, ctx, isAssigned);
|
|
21473
|
+
return setNodeLoc(lowerExpressionImpl(expr, ctx, isAssigned), expr.loc);
|
|
21307
21474
|
} finally {
|
|
21308
21475
|
ctx.expressionDepth = depth - 1;
|
|
21309
21476
|
}
|
|
21310
21477
|
}
|
|
21311
|
-
function lowerExpressionImpl(expr, ctx,
|
|
21478
|
+
function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
|
|
21312
21479
|
const { t: t2 } = ctx;
|
|
21313
21480
|
const mapParams = (params) => params.map((p) => t2.identifier(deSSAVarName(p.name)));
|
|
21314
21481
|
const withFunctionScope = (paramNames, fn) => {
|
|
@@ -21370,11 +21537,7 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21370
21537
|
};
|
|
21371
21538
|
const declared = new Set(paramIds.map((p) => p.name));
|
|
21372
21539
|
return lowerStructuredNodeWithoutRegions(structured, t2, ctx, declared);
|
|
21373
|
-
} catch
|
|
21374
|
-
console.log(
|
|
21375
|
-
"[DEBUG] Structurization failed, falling back to lowerBlocksToStatements via lowerInstruction",
|
|
21376
|
-
e
|
|
21377
|
-
);
|
|
21540
|
+
} catch {
|
|
21378
21541
|
return lowerBlocksToStatements(blocks);
|
|
21379
21542
|
}
|
|
21380
21543
|
};
|
|
@@ -21438,14 +21601,22 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21438
21601
|
const calleeIsMemoAccessor = !!calleeName && ctx.memoVars?.has(calleeName);
|
|
21439
21602
|
const calleeIsSignalLike = !!calleeName && (ctx.signalVars?.has(calleeName) || ctx.storeVars?.has(calleeName));
|
|
21440
21603
|
if (calleeIsMemoAccessor && !calleeIsSignalLike && expr.arguments.length > 0) {
|
|
21441
|
-
const
|
|
21442
|
-
return t2.callExpression(t2.callExpression(t2.identifier(calleeName), []),
|
|
21604
|
+
const loweredArgs2 = expr.arguments.map((a) => lowerExpression(a, ctx));
|
|
21605
|
+
return t2.callExpression(t2.callExpression(t2.identifier(calleeName), []), loweredArgs2);
|
|
21443
21606
|
}
|
|
21444
21607
|
const lowerCallee = () => isIIFE ? withNonReactiveScope(ctx, () => lowerExpression(expr.callee, ctx)) : lowerExpression(expr.callee, ctx);
|
|
21445
|
-
|
|
21446
|
-
|
|
21447
|
-
|
|
21448
|
-
|
|
21608
|
+
const isIteratingMethod = expr.callee.kind === "MemberExpression" && (expr.callee.property.kind === "Identifier" && ["map", "reduce", "forEach", "filter", "flatMap", "some", "every", "find"].includes(
|
|
21609
|
+
expr.callee.property.name
|
|
21610
|
+
) || expr.callee.property.kind === "Literal" && ["map", "reduce", "forEach", "filter", "flatMap", "some", "every", "find"].includes(
|
|
21611
|
+
String(expr.callee.property.value)
|
|
21612
|
+
));
|
|
21613
|
+
const loweredArgs = expr.arguments.map((a, idx) => {
|
|
21614
|
+
if (idx === 0 && isIteratingMethod && (a.kind === "ArrowFunction" || a.kind === "FunctionExpression")) {
|
|
21615
|
+
return withNoMemoAndDynamicHooks(ctx, () => lowerExpression(a, ctx));
|
|
21616
|
+
}
|
|
21617
|
+
return lowerExpression(a, ctx);
|
|
21618
|
+
});
|
|
21619
|
+
return t2.callExpression(lowerCallee(), loweredArgs);
|
|
21449
21620
|
}
|
|
21450
21621
|
case "MemberExpression":
|
|
21451
21622
|
if (matchesListKeyPattern(expr, ctx)) {
|
|
@@ -21545,12 +21716,10 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21545
21716
|
case "ArrowFunction": {
|
|
21546
21717
|
const paramIds = mapParams(expr.params);
|
|
21547
21718
|
const shadowed = new Set(expr.params.map((p) => deSSAVarName(p.name)));
|
|
21548
|
-
return
|
|
21549
|
-
|
|
21550
|
-
|
|
21551
|
-
|
|
21552
|
-
let fn;
|
|
21553
|
-
try {
|
|
21719
|
+
return withNonReactiveScope(
|
|
21720
|
+
ctx,
|
|
21721
|
+
() => withFunctionScope(shadowed, () => {
|
|
21722
|
+
let fn;
|
|
21554
21723
|
if (expr.isExpression && !Array.isArray(expr.body)) {
|
|
21555
21724
|
const { result: bodyExpr, cacheDeclarations } = withGetterCache(
|
|
21556
21725
|
ctx,
|
|
@@ -21578,12 +21747,8 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21578
21747
|
}
|
|
21579
21748
|
fn.async = expr.isAsync ?? false;
|
|
21580
21749
|
return fn;
|
|
21581
|
-
}
|
|
21582
|
-
|
|
21583
|
-
ctx.nonReactiveScopeDepth = (ctx.nonReactiveScopeDepth ?? 0) - 1;
|
|
21584
|
-
}
|
|
21585
|
-
}
|
|
21586
|
-
});
|
|
21750
|
+
})
|
|
21751
|
+
);
|
|
21587
21752
|
}
|
|
21588
21753
|
case "FunctionExpression": {
|
|
21589
21754
|
const paramIds = mapParams(expr.params);
|
|
@@ -22302,15 +22467,6 @@ function isStaticValue(expr) {
|
|
|
22302
22467
|
if (!expr) return false;
|
|
22303
22468
|
return expr.kind === "Literal";
|
|
22304
22469
|
}
|
|
22305
|
-
function isComponentLikeCallee(expr) {
|
|
22306
|
-
if (expr.kind === "Identifier") {
|
|
22307
|
-
return expr.name[0] === expr.name[0]?.toUpperCase();
|
|
22308
|
-
}
|
|
22309
|
-
if (expr.kind === "MemberExpression" || expr.kind === "OptionalMemberExpression") {
|
|
22310
|
-
return isComponentLikeCallee(expr.object);
|
|
22311
|
-
}
|
|
22312
|
-
return false;
|
|
22313
|
-
}
|
|
22314
22470
|
function isLikelyTextExpression(expr, ctx) {
|
|
22315
22471
|
let ok = true;
|
|
22316
22472
|
const isReactiveIdentifier = (name) => {
|
|
@@ -22339,15 +22495,9 @@ function isLikelyTextExpression(expr, ctx) {
|
|
|
22339
22495
|
ok = false;
|
|
22340
22496
|
return;
|
|
22341
22497
|
case "CallExpression":
|
|
22342
|
-
case "OptionalCallExpression":
|
|
22343
|
-
|
|
22344
|
-
ok = false;
|
|
22345
|
-
return;
|
|
22346
|
-
}
|
|
22347
|
-
visit(node.callee, true);
|
|
22348
|
-
node.arguments.forEach((arg) => visit(arg));
|
|
22498
|
+
case "OptionalCallExpression":
|
|
22499
|
+
ok = false;
|
|
22349
22500
|
return;
|
|
22350
|
-
}
|
|
22351
22501
|
case "MemberExpression":
|
|
22352
22502
|
case "OptionalMemberExpression":
|
|
22353
22503
|
visit(node.object, true);
|
|
@@ -22779,16 +22929,28 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
22779
22929
|
t2.expressionStatement(lowerDomExpression(binding.expr, ctx, containingRegion))
|
|
22780
22930
|
);
|
|
22781
22931
|
} else if (binding.type === "text" && binding.expr) {
|
|
22782
|
-
ctx.helpersUsed.add("bindText");
|
|
22783
22932
|
const valueExpr = lowerDomExpression(binding.expr, ctx, containingRegion);
|
|
22784
|
-
|
|
22785
|
-
|
|
22786
|
-
|
|
22787
|
-
|
|
22788
|
-
t2.
|
|
22789
|
-
|
|
22790
|
-
|
|
22791
|
-
|
|
22933
|
+
if (isExpressionReactive(binding.expr, ctx)) {
|
|
22934
|
+
ctx.helpersUsed.add("bindText");
|
|
22935
|
+
statements.push(
|
|
22936
|
+
t2.expressionStatement(
|
|
22937
|
+
t2.callExpression(t2.identifier(RUNTIME_ALIASES.bindText), [
|
|
22938
|
+
targetId,
|
|
22939
|
+
t2.arrowFunctionExpression([], valueExpr)
|
|
22940
|
+
])
|
|
22941
|
+
)
|
|
22942
|
+
);
|
|
22943
|
+
} else {
|
|
22944
|
+
statements.push(
|
|
22945
|
+
t2.expressionStatement(
|
|
22946
|
+
t2.assignmentExpression(
|
|
22947
|
+
"=",
|
|
22948
|
+
t2.memberExpression(targetId, t2.identifier("data")),
|
|
22949
|
+
t2.callExpression(t2.identifier("String"), [valueExpr])
|
|
22950
|
+
)
|
|
22951
|
+
)
|
|
22952
|
+
);
|
|
22953
|
+
}
|
|
22792
22954
|
} else if (binding.type === "child" && binding.expr) {
|
|
22793
22955
|
emitHIRChildBinding(targetId, binding.expr, statements, ctx, containingRegion);
|
|
22794
22956
|
}
|
|
@@ -22802,7 +22964,12 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
22802
22964
|
t2.arrowFunctionExpression([], body)
|
|
22803
22965
|
];
|
|
22804
22966
|
if (ctx.isComponentFn) {
|
|
22805
|
-
|
|
22967
|
+
{
|
|
22968
|
+
const slot = reserveHookSlot2(ctx);
|
|
22969
|
+
if (slot >= 0) {
|
|
22970
|
+
memoArgs.push(t2.numericLiteral(slot));
|
|
22971
|
+
}
|
|
22972
|
+
}
|
|
22806
22973
|
}
|
|
22807
22974
|
return t2.callExpression(t2.callExpression(t2.identifier(RUNTIME_ALIASES.useMemo), memoArgs), []);
|
|
22808
22975
|
}
|
|
@@ -23097,8 +23264,13 @@ function getTrackedCallIdentifier(expr, ctx, itemParamName) {
|
|
|
23097
23264
|
}
|
|
23098
23265
|
return null;
|
|
23099
23266
|
}
|
|
23100
|
-
function rewriteSelectorExpression(expr, itemParamName, getSelectorId, ctx) {
|
|
23267
|
+
function rewriteSelectorExpression(expr, itemParamName, keyParamName, getSelectorId, ctx) {
|
|
23101
23268
|
const { t: t2 } = ctx;
|
|
23269
|
+
const usesParamIdentifier = (e) => {
|
|
23270
|
+
if (expressionUsesIdentifier(e, itemParamName, t2)) return true;
|
|
23271
|
+
if (keyParamName && expressionUsesIdentifier(e, keyParamName, t2)) return true;
|
|
23272
|
+
return false;
|
|
23273
|
+
};
|
|
23102
23274
|
if (t2.isBinaryExpression(expr) && (expr.operator === "===" || expr.operator === "==")) {
|
|
23103
23275
|
const leftTracked = getTrackedCallIdentifier(
|
|
23104
23276
|
expr.left,
|
|
@@ -23110,7 +23282,7 @@ function rewriteSelectorExpression(expr, itemParamName, getSelectorId, ctx) {
|
|
|
23110
23282
|
ctx,
|
|
23111
23283
|
itemParamName
|
|
23112
23284
|
);
|
|
23113
|
-
if (leftTracked &&
|
|
23285
|
+
if (leftTracked && usesParamIdentifier(expr.right)) {
|
|
23114
23286
|
return {
|
|
23115
23287
|
expr: t2.callExpression(getSelectorId(leftTracked), [
|
|
23116
23288
|
expr.right
|
|
@@ -23118,7 +23290,7 @@ function rewriteSelectorExpression(expr, itemParamName, getSelectorId, ctx) {
|
|
|
23118
23290
|
changed: true
|
|
23119
23291
|
};
|
|
23120
23292
|
}
|
|
23121
|
-
if (rightTracked &&
|
|
23293
|
+
if (rightTracked && usesParamIdentifier(expr.left)) {
|
|
23122
23294
|
return {
|
|
23123
23295
|
expr: t2.callExpression(getSelectorId(rightTracked), [
|
|
23124
23296
|
expr.left
|
|
@@ -23129,7 +23301,7 @@ function rewriteSelectorExpression(expr, itemParamName, getSelectorId, ctx) {
|
|
|
23129
23301
|
}
|
|
23130
23302
|
let changed = false;
|
|
23131
23303
|
const rewrite = (node) => {
|
|
23132
|
-
const result = rewriteSelectorExpression(node, itemParamName, getSelectorId, ctx);
|
|
23304
|
+
const result = rewriteSelectorExpression(node, itemParamName, keyParamName, getSelectorId, ctx);
|
|
23133
23305
|
if (result.changed) changed = true;
|
|
23134
23306
|
return result.expr;
|
|
23135
23307
|
};
|
|
@@ -23190,7 +23362,7 @@ function rewriteSelectorExpression(expr, itemParamName, getSelectorId, ctx) {
|
|
|
23190
23362
|
}
|
|
23191
23363
|
return { expr, changed };
|
|
23192
23364
|
}
|
|
23193
|
-
function applySelectorHoist(callbackExpr, itemParamName, statements, ctx) {
|
|
23365
|
+
function applySelectorHoist(callbackExpr, itemParamName, keyParamName, statements, ctx) {
|
|
23194
23366
|
const { t: t2 } = ctx;
|
|
23195
23367
|
if (!itemParamName) return;
|
|
23196
23368
|
if (!t2.isArrowFunctionExpression(callbackExpr) && !t2.isFunctionExpression(callbackExpr)) return;
|
|
@@ -23206,7 +23378,13 @@ function applySelectorHoist(callbackExpr, itemParamName, statements, ctx) {
|
|
|
23206
23378
|
if (t2.isBlockStatement(fn.body)) {
|
|
23207
23379
|
for (const stmt of fn.body.body) {
|
|
23208
23380
|
if (t2.isReturnStatement(stmt) && stmt.argument && t2.isExpression(stmt.argument)) {
|
|
23209
|
-
const result = rewriteSelectorExpression(
|
|
23381
|
+
const result = rewriteSelectorExpression(
|
|
23382
|
+
stmt.argument,
|
|
23383
|
+
itemParamName,
|
|
23384
|
+
keyParamName,
|
|
23385
|
+
getSelectorId,
|
|
23386
|
+
ctx
|
|
23387
|
+
);
|
|
23210
23388
|
if (result.changed) {
|
|
23211
23389
|
stmt.argument = result.expr;
|
|
23212
23390
|
}
|
|
@@ -23215,7 +23393,13 @@ function applySelectorHoist(callbackExpr, itemParamName, statements, ctx) {
|
|
|
23215
23393
|
return;
|
|
23216
23394
|
}
|
|
23217
23395
|
if (t2.isExpression(fn.body)) {
|
|
23218
|
-
const result = rewriteSelectorExpression(
|
|
23396
|
+
const result = rewriteSelectorExpression(
|
|
23397
|
+
fn.body,
|
|
23398
|
+
itemParamName,
|
|
23399
|
+
keyParamName,
|
|
23400
|
+
getSelectorId,
|
|
23401
|
+
ctx
|
|
23402
|
+
);
|
|
23219
23403
|
if (result.changed) {
|
|
23220
23404
|
fn.body = result.expr;
|
|
23221
23405
|
}
|
|
@@ -23357,12 +23541,16 @@ function emitListChild(parentId, markerId, expr, statements, ctx) {
|
|
|
23357
23541
|
const hoistedStatements = ctx.hoistedTemplateStatements;
|
|
23358
23542
|
ctx.hoistedTemplates = prevHoistedTemplates;
|
|
23359
23543
|
ctx.hoistedTemplateStatements = prevHoistedTemplateStatements;
|
|
23360
|
-
if (
|
|
23361
|
-
const firstParam = callbackExpr.params
|
|
23544
|
+
if (t2.isArrowFunctionExpression(callbackExpr) || t2.isFunctionExpression(callbackExpr)) {
|
|
23545
|
+
const [firstParam, secondParam] = callbackExpr.params;
|
|
23546
|
+
const overrides = {};
|
|
23362
23547
|
if (t2.isIdentifier(firstParam)) {
|
|
23363
|
-
|
|
23364
|
-
|
|
23365
|
-
|
|
23548
|
+
overrides[firstParam.name] = () => t2.callExpression(t2.identifier(firstParam.name), []);
|
|
23549
|
+
}
|
|
23550
|
+
if (t2.isIdentifier(secondParam)) {
|
|
23551
|
+
overrides[secondParam.name] = () => t2.callExpression(t2.identifier(secondParam.name), []);
|
|
23552
|
+
}
|
|
23553
|
+
if (Object.keys(overrides).length > 0) {
|
|
23366
23554
|
if (t2.isBlockStatement(callbackExpr.body)) {
|
|
23367
23555
|
replaceIdentifiersWithOverrides(callbackExpr.body, overrides, t2, callbackExpr.type, "body");
|
|
23368
23556
|
} else {
|
|
@@ -23375,7 +23563,14 @@ function emitListChild(parentId, markerId, expr, statements, ctx) {
|
|
|
23375
23563
|
const listId = genTemp(ctx, "list");
|
|
23376
23564
|
if (isKeyed) {
|
|
23377
23565
|
const itemParamName = t2.isArrowFunctionExpression(callbackExpr) || t2.isFunctionExpression(callbackExpr) ? t2.isIdentifier(callbackExpr.params[0]) ? callbackExpr.params[0].name : null : null;
|
|
23378
|
-
|
|
23566
|
+
const keyParamName = ctx.listKeyParamName ?? null;
|
|
23567
|
+
applySelectorHoist(
|
|
23568
|
+
callbackExpr,
|
|
23569
|
+
itemParamName,
|
|
23570
|
+
keyParamName,
|
|
23571
|
+
statements,
|
|
23572
|
+
ctx
|
|
23573
|
+
);
|
|
23379
23574
|
}
|
|
23380
23575
|
if (isKeyed && keyExpr) {
|
|
23381
23576
|
let keyExprAst = lowerExpression(keyExpr, ctx);
|
|
@@ -24256,10 +24451,9 @@ function lowerFunctionWithRegions(fn, ctx) {
|
|
|
24256
24451
|
}
|
|
24257
24452
|
}
|
|
24258
24453
|
const params = finalParams;
|
|
24259
|
-
const funcDecl =
|
|
24260
|
-
t2.identifier(fn.name ?? "fn"),
|
|
24261
|
-
|
|
24262
|
-
t2.blockStatement(statements)
|
|
24454
|
+
const funcDecl = setNodeLoc(
|
|
24455
|
+
t2.functionDeclaration(t2.identifier(fn.name ?? "fn"), params, t2.blockStatement(statements)),
|
|
24456
|
+
fn.loc
|
|
24263
24457
|
);
|
|
24264
24458
|
ctx.needsCtx = prevNeedsCtx;
|
|
24265
24459
|
ctx.shadowedNames = prevShadowed;
|
|
@@ -24348,10 +24542,44 @@ function isInsideNestedFunction(path) {
|
|
|
24348
24542
|
function isInsideJSX(path) {
|
|
24349
24543
|
return !!path.findParent((p) => p.isJSXElement?.() || p.isJSXFragment?.());
|
|
24350
24544
|
}
|
|
24351
|
-
function
|
|
24352
|
-
if (!
|
|
24545
|
+
function parseSuppressionCodes(raw) {
|
|
24546
|
+
if (!raw) return void 0;
|
|
24547
|
+
const codes = raw.split(/[,\s]+/).map((c) => c.trim()).filter(Boolean);
|
|
24548
|
+
return codes.length > 0 ? new Set(codes) : void 0;
|
|
24549
|
+
}
|
|
24550
|
+
function parseSuppressions(comments) {
|
|
24551
|
+
if (!comments) return [];
|
|
24552
|
+
const suppressions = [];
|
|
24553
|
+
for (const comment of comments) {
|
|
24554
|
+
const match = comment.value.match(/fict-ignore(-next-line)?(?:\s+(.+))?/i);
|
|
24555
|
+
if (!match || !comment.loc) continue;
|
|
24556
|
+
suppressions.push({
|
|
24557
|
+
line: comment.loc.start.line,
|
|
24558
|
+
nextLine: !!match[1],
|
|
24559
|
+
codes: parseSuppressionCodes(match[2])
|
|
24560
|
+
});
|
|
24561
|
+
}
|
|
24562
|
+
return suppressions;
|
|
24563
|
+
}
|
|
24564
|
+
function shouldSuppressWarning(suppressions, code, line) {
|
|
24565
|
+
return suppressions.some((entry) => {
|
|
24566
|
+
const targetLine = entry.nextLine ? entry.line + 1 : entry.line;
|
|
24567
|
+
if (targetLine !== line) return false;
|
|
24568
|
+
if (!entry.codes || entry.codes.size === 0) return true;
|
|
24569
|
+
return entry.codes.has(code);
|
|
24570
|
+
});
|
|
24571
|
+
}
|
|
24572
|
+
function createWarningDispatcher(onWarn, suppressions) {
|
|
24573
|
+
if (!onWarn) return () => {
|
|
24574
|
+
};
|
|
24575
|
+
return (warning) => {
|
|
24576
|
+
if (shouldSuppressWarning(suppressions, warning.code, warning.line)) return;
|
|
24577
|
+
onWarn(warning);
|
|
24578
|
+
};
|
|
24579
|
+
}
|
|
24580
|
+
function emitWarning(node, code, message, warn, fileName) {
|
|
24353
24581
|
const loc = node.loc?.start;
|
|
24354
|
-
|
|
24582
|
+
warn({
|
|
24355
24583
|
code,
|
|
24356
24584
|
message,
|
|
24357
24585
|
fileName,
|
|
@@ -24439,8 +24667,7 @@ function isDynamicPropertyAccess(node, t2) {
|
|
|
24439
24667
|
if (!node.computed) return false;
|
|
24440
24668
|
return !(t2.isStringLiteral(node.property) || t2.isNumericLiteral(node.property));
|
|
24441
24669
|
}
|
|
24442
|
-
function runWarningPass(programPath, stateVars, derivedVars,
|
|
24443
|
-
const fileName = programPath.hub?.file?.opts?.filename || "<unknown>";
|
|
24670
|
+
function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t2) {
|
|
24444
24671
|
const isStateRoot = (expr) => {
|
|
24445
24672
|
const root = getRootIdentifier(expr, t2);
|
|
24446
24673
|
return !!(root && stateVars.has(root.name));
|
|
@@ -24456,7 +24683,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24456
24683
|
path.node,
|
|
24457
24684
|
"FICT-M",
|
|
24458
24685
|
"Direct mutation of nested property detected; use immutable update or $store helpers",
|
|
24459
|
-
|
|
24686
|
+
warn,
|
|
24460
24687
|
fileName
|
|
24461
24688
|
);
|
|
24462
24689
|
if (isDynamicPropertyAccess(left, t2)) {
|
|
@@ -24464,7 +24691,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24464
24691
|
path.node,
|
|
24465
24692
|
"FICT-H",
|
|
24466
24693
|
"Dynamic property access widens dependency tracking",
|
|
24467
|
-
|
|
24694
|
+
warn,
|
|
24468
24695
|
fileName
|
|
24469
24696
|
);
|
|
24470
24697
|
}
|
|
@@ -24479,7 +24706,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24479
24706
|
path.node,
|
|
24480
24707
|
"FICT-M",
|
|
24481
24708
|
"Direct mutation of nested property detected; use immutable update or $store helpers",
|
|
24482
|
-
|
|
24709
|
+
warn,
|
|
24483
24710
|
fileName
|
|
24484
24711
|
);
|
|
24485
24712
|
if (isDynamicPropertyAccess(arg, t2)) {
|
|
@@ -24487,7 +24714,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24487
24714
|
path.node,
|
|
24488
24715
|
"FICT-H",
|
|
24489
24716
|
"Dynamic property access widens dependency tracking",
|
|
24490
|
-
|
|
24717
|
+
warn,
|
|
24491
24718
|
fileName
|
|
24492
24719
|
);
|
|
24493
24720
|
}
|
|
@@ -24503,7 +24730,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24503
24730
|
path.node,
|
|
24504
24731
|
"FICT-H",
|
|
24505
24732
|
"Dynamic property access widens dependency tracking",
|
|
24506
|
-
|
|
24733
|
+
warn,
|
|
24507
24734
|
fileName
|
|
24508
24735
|
);
|
|
24509
24736
|
}
|
|
@@ -24532,7 +24759,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24532
24759
|
path.node,
|
|
24533
24760
|
"FICT-R005",
|
|
24534
24761
|
`Function captures reactive variable(s): ${Array.from(captured).join(", ")}. Pass them as parameters or memoize explicitly to avoid hidden dependencies.`,
|
|
24535
|
-
|
|
24762
|
+
warn,
|
|
24536
24763
|
fileName
|
|
24537
24764
|
);
|
|
24538
24765
|
}
|
|
@@ -24563,7 +24790,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24563
24790
|
path.node,
|
|
24564
24791
|
"FICT-E001",
|
|
24565
24792
|
"Effect has no reactive reads; it will run once. Consider removing $effect or adding dependencies.",
|
|
24566
|
-
|
|
24793
|
+
warn,
|
|
24567
24794
|
fileName
|
|
24568
24795
|
);
|
|
24569
24796
|
}
|
|
@@ -24589,7 +24816,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24589
24816
|
arg,
|
|
24590
24817
|
"FICT-H",
|
|
24591
24818
|
"State value passed to unknown function (black box); dependency tracking may be imprecise",
|
|
24592
|
-
|
|
24819
|
+
warn,
|
|
24593
24820
|
fileName
|
|
24594
24821
|
);
|
|
24595
24822
|
break;
|
|
@@ -24605,7 +24832,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24605
24832
|
path.node,
|
|
24606
24833
|
"FICT-H",
|
|
24607
24834
|
"Dynamic property access widens dependency tracking",
|
|
24608
|
-
|
|
24835
|
+
warn,
|
|
24609
24836
|
fileName
|
|
24610
24837
|
);
|
|
24611
24838
|
}
|
|
@@ -24655,6 +24882,10 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24655
24882
|
Program: {
|
|
24656
24883
|
exit(path) {
|
|
24657
24884
|
const fileName = path.hub?.file?.opts?.filename || "<unknown>";
|
|
24885
|
+
const comments = path.hub?.file?.ast?.comments || [];
|
|
24886
|
+
const suppressions = parseSuppressions(comments);
|
|
24887
|
+
const warn = createWarningDispatcher(options.onWarn, suppressions);
|
|
24888
|
+
const optionsWithWarnings = { ...options, onWarn: warn };
|
|
24658
24889
|
const isHookName2 = (name) => !!name && /^use[A-Z]/.test(name);
|
|
24659
24890
|
const getFunctionName = (fnPath) => {
|
|
24660
24891
|
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;
|
|
@@ -24673,14 +24904,75 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24673
24904
|
return name && isComponentName(name) || isHookName2(name) || functionHasJSX(fnPath) || functionUsesStateLike(fnPath, t2);
|
|
24674
24905
|
};
|
|
24675
24906
|
const memoHasSideEffects = (fn) => {
|
|
24907
|
+
const pureCalls = new Set(
|
|
24908
|
+
Array.from(SAFE_FUNCTIONS).filter(
|
|
24909
|
+
(name) => !name.startsWith("console.") && name !== "Math.random"
|
|
24910
|
+
)
|
|
24911
|
+
);
|
|
24912
|
+
const effectfulCalls = /* @__PURE__ */ new Set([
|
|
24913
|
+
"$effect",
|
|
24914
|
+
"render",
|
|
24915
|
+
"fetch",
|
|
24916
|
+
"setTimeout",
|
|
24917
|
+
"setInterval",
|
|
24918
|
+
"clearTimeout",
|
|
24919
|
+
"clearInterval",
|
|
24920
|
+
"requestAnimationFrame",
|
|
24921
|
+
"cancelAnimationFrame"
|
|
24922
|
+
]);
|
|
24923
|
+
const getCalleeName = (callee) => {
|
|
24924
|
+
if (t2.isIdentifier(callee)) return callee.name;
|
|
24925
|
+
if (t2.isMemberExpression(callee) && !callee.computed && t2.isIdentifier(callee.property) && t2.isIdentifier(callee.object)) {
|
|
24926
|
+
return `${callee.object.name}.${callee.property.name}`;
|
|
24927
|
+
}
|
|
24928
|
+
return null;
|
|
24929
|
+
};
|
|
24930
|
+
const mutatingMemberProps = /* @__PURE__ */ new Set([
|
|
24931
|
+
"push",
|
|
24932
|
+
"pop",
|
|
24933
|
+
"splice",
|
|
24934
|
+
"shift",
|
|
24935
|
+
"unshift",
|
|
24936
|
+
"sort",
|
|
24937
|
+
"reverse",
|
|
24938
|
+
"set",
|
|
24939
|
+
"add",
|
|
24940
|
+
"delete",
|
|
24941
|
+
"append",
|
|
24942
|
+
"appendChild",
|
|
24943
|
+
"remove",
|
|
24944
|
+
"removeChild",
|
|
24945
|
+
"setAttribute",
|
|
24946
|
+
"dispatchEvent",
|
|
24947
|
+
"replaceChildren",
|
|
24948
|
+
"replaceWith"
|
|
24949
|
+
]);
|
|
24950
|
+
const isEffectfulCall = (node) => {
|
|
24951
|
+
const name = getCalleeName(node.callee);
|
|
24952
|
+
if (!name) return true;
|
|
24953
|
+
if (pureCalls.has(name)) return false;
|
|
24954
|
+
if (effectfulCalls.has(name)) return true;
|
|
24955
|
+
if (name.startsWith("console.") || name.startsWith("document.") || name.startsWith("window.")) {
|
|
24956
|
+
return true;
|
|
24957
|
+
}
|
|
24958
|
+
if (t2.isMemberExpression(node.callee) && !node.callee.computed && t2.isIdentifier(node.callee.property)) {
|
|
24959
|
+
const prop = node.callee.property.name;
|
|
24960
|
+
if (mutatingMemberProps.has(prop)) return true;
|
|
24961
|
+
if (t2.isIdentifier(node.callee.object) && (node.callee.object.name === "document" || node.callee.object.name === "window")) {
|
|
24962
|
+
return true;
|
|
24963
|
+
}
|
|
24964
|
+
}
|
|
24965
|
+
return false;
|
|
24966
|
+
};
|
|
24676
24967
|
const checkNode = (node) => {
|
|
24677
24968
|
if (!node) return false;
|
|
24678
24969
|
if (t2.isAssignmentExpression(node) || t2.isUpdateExpression(node) || t2.isThrowStatement(node) || t2.isNewExpression(node)) {
|
|
24679
24970
|
return true;
|
|
24680
24971
|
}
|
|
24681
|
-
if (t2.isCallExpression(node) && (
|
|
24972
|
+
if (t2.isCallExpression(node) && isEffectfulCall(node)) {
|
|
24682
24973
|
return true;
|
|
24683
24974
|
}
|
|
24975
|
+
if (t2.isAwaitExpression(node)) return true;
|
|
24684
24976
|
if (t2.isExpressionStatement(node)) return checkNode(node.expression);
|
|
24685
24977
|
if (t2.isBlockStatement(node)) return node.body.some((stmt) => checkNode(stmt));
|
|
24686
24978
|
if (t2.isReturnStatement(node)) return checkNode(node.argument);
|
|
@@ -24704,7 +24996,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24704
24996
|
fnPath.node,
|
|
24705
24997
|
"FICT-C004",
|
|
24706
24998
|
"Component has no return statement and will render nothing.",
|
|
24707
|
-
|
|
24999
|
+
warn,
|
|
24708
25000
|
fileName
|
|
24709
25001
|
);
|
|
24710
25002
|
},
|
|
@@ -24722,7 +25014,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24722
25014
|
init,
|
|
24723
25015
|
"FICT-C004",
|
|
24724
25016
|
"Component has no return statement and will render nothing.",
|
|
24725
|
-
|
|
25017
|
+
warn,
|
|
24726
25018
|
fileName
|
|
24727
25019
|
);
|
|
24728
25020
|
}
|
|
@@ -24772,7 +25064,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24772
25064
|
}
|
|
24773
25065
|
}
|
|
24774
25066
|
if (hasKey || hasUnknownSpread) return;
|
|
24775
|
-
|
|
25067
|
+
warn({
|
|
24776
25068
|
code: "FICT-J002",
|
|
24777
25069
|
message: "Missing key prop in list rendering.",
|
|
24778
25070
|
fileName,
|
|
@@ -24843,7 +25135,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24843
25135
|
fnPath.node,
|
|
24844
25136
|
"FICT-C003",
|
|
24845
25137
|
"Components should not be defined inside other components. Move this definition to module scope to preserve identity and performance.",
|
|
24846
|
-
|
|
25138
|
+
warn,
|
|
24847
25139
|
fileName
|
|
24848
25140
|
);
|
|
24849
25141
|
},
|
|
@@ -24888,7 +25180,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24888
25180
|
callPath.node,
|
|
24889
25181
|
"FICT-R004",
|
|
24890
25182
|
"Reactive creation inside non-JSX control flow will not auto-dispose; wrap it in createScope/runInScope or move it into JSX-managed regions.",
|
|
24891
|
-
|
|
25183
|
+
warn,
|
|
24892
25184
|
fileName
|
|
24893
25185
|
);
|
|
24894
25186
|
}
|
|
@@ -24923,7 +25215,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24923
25215
|
callPath.node.arguments.forEach((arg) => {
|
|
24924
25216
|
if (t2.isIdentifier(arg) && stateVars.has(arg.name) && (!calleeId || !allowedStateCallees.has(calleeId))) {
|
|
24925
25217
|
const loc = arg.loc?.start ?? callPath.node.loc?.start;
|
|
24926
|
-
|
|
25218
|
+
warn({
|
|
24927
25219
|
code: "FICT-S002",
|
|
24928
25220
|
message: "State variable is passed as an argument; this passes a value snapshot and may escape component scope.",
|
|
24929
25221
|
fileName,
|
|
@@ -24936,7 +25228,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24936
25228
|
const firstArg = callPath.node.arguments[0];
|
|
24937
25229
|
if (firstArg && (t2.isArrowFunctionExpression(firstArg) || t2.isFunctionExpression(firstArg)) && memoHasSideEffects(firstArg)) {
|
|
24938
25230
|
const loc = firstArg.loc?.start ?? callPath.node.loc?.start;
|
|
24939
|
-
|
|
25231
|
+
warn({
|
|
24940
25232
|
code: "FICT-M003",
|
|
24941
25233
|
message: "Memo should not contain side effects.",
|
|
24942
25234
|
fileName,
|
|
@@ -25041,10 +25333,10 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
25041
25333
|
}
|
|
25042
25334
|
});
|
|
25043
25335
|
}
|
|
25044
|
-
runWarningPass(path, stateVars, derivedVars,
|
|
25336
|
+
runWarningPass(path, stateVars, derivedVars, warn, fileName, t2);
|
|
25045
25337
|
const fileAst = t2.file(path.node);
|
|
25046
25338
|
const hir = buildHIR(fileAst);
|
|
25047
|
-
const lowered = lowerHIRWithRegions(hir, t2,
|
|
25339
|
+
const lowered = lowerHIRWithRegions(hir, t2, optionsWithWarnings);
|
|
25048
25340
|
path.node.body = lowered.program.body;
|
|
25049
25341
|
path.node.directives = lowered.program.directives;
|
|
25050
25342
|
if (!process.env.FICT_SKIP_SCOPE_CRAWL) {
|