@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.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
|
|
|
@@ -18272,7 +18331,8 @@ function lowerNodeWithRegionContext(node, t2, ctx, declaredVars, regionCtx) {
|
|
|
18272
18331
|
t2.blockStatement(conseqStmts),
|
|
18273
18332
|
altStmts ? t2.blockStatement(altStmts) : null
|
|
18274
18333
|
);
|
|
18275
|
-
const
|
|
18334
|
+
const inNonReactiveScope = !!(ctx.nonReactiveScopeDepth && ctx.nonReactiveScopeDepth > 0);
|
|
18335
|
+
const shouldWrapEffect = ctx.wrapTrackedExpressions !== false && !ctx.inRegionMemo && !inNonReactiveScope && expressionUsesTracked(node.test, ctx) && !statementHasEarlyExit(ifStmt, t2);
|
|
18276
18336
|
if (shouldWrapEffect) {
|
|
18277
18337
|
ctx.helpersUsed.add("useEffect");
|
|
18278
18338
|
ctx.needsCtx = true;
|
|
@@ -18500,31 +18560,53 @@ function lowerStructuredNodeForRegion(node, region, t2, ctx, declaredVars, regio
|
|
|
18500
18560
|
return stmt ? [stmt] : [];
|
|
18501
18561
|
}
|
|
18502
18562
|
case "if": {
|
|
18503
|
-
const
|
|
18504
|
-
|
|
18505
|
-
|
|
18506
|
-
|
|
18507
|
-
|
|
18508
|
-
|
|
18509
|
-
|
|
18510
|
-
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
|
|
18514
|
-
|
|
18515
|
-
|
|
18516
|
-
|
|
18517
|
-
|
|
18518
|
-
|
|
18519
|
-
|
|
18520
|
-
|
|
18563
|
+
const inNonReactiveScope = !!(ctx.nonReactiveScopeDepth && ctx.nonReactiveScopeDepth > 0);
|
|
18564
|
+
const baseShouldWrapEffect = ctx.wrapTrackedExpressions !== false && !ctx.inRegionMemo && !inNonReactiveScope && expressionUsesTracked(node.test, ctx);
|
|
18565
|
+
const lowerChild = (child, forceNonReactive) => {
|
|
18566
|
+
if (!child) return [];
|
|
18567
|
+
if (!forceNonReactive) {
|
|
18568
|
+
return lowerStructuredNodeForRegion(
|
|
18569
|
+
child,
|
|
18570
|
+
region,
|
|
18571
|
+
t2,
|
|
18572
|
+
ctx,
|
|
18573
|
+
declaredVars,
|
|
18574
|
+
regionCtx,
|
|
18575
|
+
skipInstructions
|
|
18576
|
+
);
|
|
18577
|
+
}
|
|
18578
|
+
const prevDepth = ctx.nonReactiveScopeDepth ?? 0;
|
|
18579
|
+
ctx.nonReactiveScopeDepth = prevDepth + 1;
|
|
18580
|
+
try {
|
|
18581
|
+
return lowerStructuredNodeForRegion(
|
|
18582
|
+
child,
|
|
18583
|
+
region,
|
|
18584
|
+
t2,
|
|
18585
|
+
ctx,
|
|
18586
|
+
declaredVars,
|
|
18587
|
+
regionCtx,
|
|
18588
|
+
skipInstructions
|
|
18589
|
+
);
|
|
18590
|
+
} finally {
|
|
18591
|
+
ctx.nonReactiveScopeDepth = prevDepth;
|
|
18592
|
+
}
|
|
18593
|
+
};
|
|
18594
|
+
let consequent = lowerChild(node.consequent, baseShouldWrapEffect);
|
|
18595
|
+
let alternate = node.alternate ? lowerChild(node.alternate, baseShouldWrapEffect) : [];
|
|
18521
18596
|
if (consequent.length === 0 && alternate.length === 0) return [];
|
|
18522
|
-
const
|
|
18597
|
+
const buildIfStmt = (cons, alt) => t2.ifStatement(
|
|
18523
18598
|
lowerExpressionWithDeSSA(node.test, ctx),
|
|
18524
|
-
t2.blockStatement(
|
|
18525
|
-
|
|
18599
|
+
t2.blockStatement(cons),
|
|
18600
|
+
alt.length > 0 ? t2.blockStatement(alt) : null
|
|
18526
18601
|
);
|
|
18527
|
-
|
|
18602
|
+
let ifStmt = buildIfStmt(consequent, alternate);
|
|
18603
|
+
const shouldWrapEffect = baseShouldWrapEffect && !statementHasEarlyExit(ifStmt, t2);
|
|
18604
|
+
if (!shouldWrapEffect && baseShouldWrapEffect) {
|
|
18605
|
+
consequent = lowerChild(node.consequent, false);
|
|
18606
|
+
alternate = node.alternate ? lowerChild(node.alternate, false) : [];
|
|
18607
|
+
if (consequent.length === 0 && alternate.length === 0) return [];
|
|
18608
|
+
ifStmt = buildIfStmt(consequent, alternate);
|
|
18609
|
+
}
|
|
18528
18610
|
if (shouldWrapEffect) {
|
|
18529
18611
|
ctx.helpersUsed.add("useEffect");
|
|
18530
18612
|
ctx.needsCtx = true;
|
|
@@ -18916,11 +18998,17 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
18916
18998
|
if (uniqueOutputNames.length === 0) {
|
|
18917
18999
|
ctx.helpersUsed.add("useEffect");
|
|
18918
19000
|
ctx.needsCtx = true;
|
|
18919
|
-
const
|
|
19001
|
+
const effectCallArgs = [
|
|
18920
19002
|
t2.identifier("__fictCtx"),
|
|
18921
|
-
t2.arrowFunctionExpression([], t2.blockStatement(bodyStatements))
|
|
18922
|
-
|
|
18923
|
-
|
|
19003
|
+
t2.arrowFunctionExpression([], t2.blockStatement(bodyStatements))
|
|
19004
|
+
];
|
|
19005
|
+
{
|
|
19006
|
+
const slot = reserveHookSlot(ctx);
|
|
19007
|
+
if (slot >= 0) {
|
|
19008
|
+
effectCallArgs.push(t2.numericLiteral(slot));
|
|
19009
|
+
}
|
|
19010
|
+
}
|
|
19011
|
+
const effectCall = t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), effectCallArgs);
|
|
18924
19012
|
statements.push(t2.expressionStatement(effectCall));
|
|
18925
19013
|
} else {
|
|
18926
19014
|
ctx.helpersUsed.add("useMemo");
|
|
@@ -18953,11 +19041,15 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
18953
19041
|
};
|
|
18954
19042
|
const returnObj = t2.objectExpression(uniqueOutputNames.map((name) => buildOutputProperty(name)));
|
|
18955
19043
|
const memoBody = t2.blockStatement([...bodyStatements, t2.returnStatement(returnObj)]);
|
|
18956
|
-
const
|
|
19044
|
+
const slot = reserveHookSlot(ctx);
|
|
19045
|
+
const memoArgs = [
|
|
18957
19046
|
t2.identifier("__fictCtx"),
|
|
18958
|
-
t2.arrowFunctionExpression([], memoBody)
|
|
18959
|
-
|
|
18960
|
-
|
|
19047
|
+
t2.arrowFunctionExpression([], memoBody)
|
|
19048
|
+
];
|
|
19049
|
+
if (slot >= 0) {
|
|
19050
|
+
memoArgs.push(t2.numericLiteral(slot));
|
|
19051
|
+
}
|
|
19052
|
+
const memoCall = t2.callExpression(t2.identifier(RUNTIME_ALIASES.useMemo), memoArgs);
|
|
18961
19053
|
const regionVarName = `__region_${region.id}`;
|
|
18962
19054
|
statements.push(
|
|
18963
19055
|
t2.variableDeclaration("const", [t2.variableDeclarator(t2.identifier(regionVarName), memoCall)])
|
|
@@ -19014,7 +19106,10 @@ function wrapInMemo(region, t2, declaredVars, ctx, bodyStatementsOverride, outpu
|
|
|
19014
19106
|
t2.callExpression(t2.identifier(RUNTIME_ALIASES.useEffect), [
|
|
19015
19107
|
t2.identifier("__fictCtx"),
|
|
19016
19108
|
t2.arrowFunctionExpression([], effectBody),
|
|
19017
|
-
|
|
19109
|
+
(() => {
|
|
19110
|
+
const slot2 = reserveHookSlot(ctx);
|
|
19111
|
+
return slot2 >= 0 ? t2.numericLiteral(slot2) : t2.identifier("undefined");
|
|
19112
|
+
})()
|
|
19018
19113
|
])
|
|
19019
19114
|
)
|
|
19020
19115
|
);
|
|
@@ -19232,11 +19327,15 @@ function generateLazyConditionalMemo(region, orderedOutputs, bodyStatements, con
|
|
|
19232
19327
|
ctx.helpersUsed.add("useMemo");
|
|
19233
19328
|
ctx.needsCtx = true;
|
|
19234
19329
|
const regionVarName = `__region_${region.id}`;
|
|
19235
|
-
const
|
|
19330
|
+
const slotForMemo = reserveHookSlot(ctx);
|
|
19331
|
+
const memoArgs = [
|
|
19236
19332
|
t2.identifier("__fictCtx"),
|
|
19237
|
-
t2.arrowFunctionExpression([], t2.blockStatement(memoBody))
|
|
19238
|
-
|
|
19239
|
-
|
|
19333
|
+
t2.arrowFunctionExpression([], t2.blockStatement(memoBody))
|
|
19334
|
+
];
|
|
19335
|
+
if (slotForMemo >= 0) {
|
|
19336
|
+
memoArgs.push(t2.numericLiteral(slotForMemo));
|
|
19337
|
+
}
|
|
19338
|
+
const memoCall = t2.callExpression(t2.identifier("__fictUseMemo"), memoArgs);
|
|
19240
19339
|
statements.push(
|
|
19241
19340
|
t2.variableDeclaration("const", [t2.variableDeclarator(t2.identifier(regionVarName), memoCall)])
|
|
19242
19341
|
);
|
|
@@ -19258,6 +19357,9 @@ function generateLazyConditionalMemo(region, orderedOutputs, bodyStatements, con
|
|
|
19258
19357
|
return statements;
|
|
19259
19358
|
}
|
|
19260
19359
|
function reserveHookSlot(ctx) {
|
|
19360
|
+
if (ctx.dynamicHookSlotDepth && ctx.dynamicHookSlotDepth > 0) {
|
|
19361
|
+
return -1;
|
|
19362
|
+
}
|
|
19261
19363
|
const slot = ctx.nextHookSlot ?? 0;
|
|
19262
19364
|
ctx.nextHookSlot = slot + 1;
|
|
19263
19365
|
return slot;
|
|
@@ -19328,7 +19430,10 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19328
19430
|
t2.arrowFunctionExpression([], expr)
|
|
19329
19431
|
];
|
|
19330
19432
|
if (inRegionMemo) {
|
|
19331
|
-
|
|
19433
|
+
const slot = reserveHookSlot(ctx);
|
|
19434
|
+
if (slot >= 0) {
|
|
19435
|
+
args.push(t2.numericLiteral(slot));
|
|
19436
|
+
}
|
|
19332
19437
|
}
|
|
19333
19438
|
ctx.helpersUsed.add("useMemo");
|
|
19334
19439
|
ctx.needsCtx = true;
|
|
@@ -19528,7 +19633,8 @@ function instructionToStatement(instr, t2, declaredVars, ctx, _buildMemoCall) {
|
|
|
19528
19633
|
(dep) => ctx.trackedVars.has(deSSAVarName(dep))
|
|
19529
19634
|
);
|
|
19530
19635
|
const usesTracked = expressionUsesTracked(instr.value, ctx);
|
|
19531
|
-
const
|
|
19636
|
+
const inNonReactiveScope = !!(ctx.nonReactiveScopeDepth && ctx.nonReactiveScopeDepth > 0);
|
|
19637
|
+
const shouldWrapExpr = ctx.wrapTrackedExpressions !== false && !inNonReactiveScope && (usesTracked || hasTrackedControlDep);
|
|
19532
19638
|
if (shouldWrapExpr) {
|
|
19533
19639
|
ctx.helpersUsed.add("useEffect");
|
|
19534
19640
|
ctx.needsCtx = true;
|
|
@@ -19843,6 +19949,17 @@ function deSSAJSXChild(child, t2) {
|
|
|
19843
19949
|
// src/ir/codegen.ts
|
|
19844
19950
|
var HOOK_SLOT_BASE = 1e3;
|
|
19845
19951
|
var HOOK_NAME_PREFIX = "use";
|
|
19952
|
+
var cloneLoc = (loc) => loc === void 0 ? void 0 : loc === null ? null : {
|
|
19953
|
+
start: { ...loc.start },
|
|
19954
|
+
end: { ...loc.end },
|
|
19955
|
+
filename: loc.filename,
|
|
19956
|
+
identifierName: loc.identifierName
|
|
19957
|
+
};
|
|
19958
|
+
function setNodeLoc(node, loc) {
|
|
19959
|
+
if (loc === void 0) return node;
|
|
19960
|
+
node.loc = cloneLoc(loc) ?? null;
|
|
19961
|
+
return node;
|
|
19962
|
+
}
|
|
19846
19963
|
function isHookName(name) {
|
|
19847
19964
|
return !!name && name.startsWith(HOOK_NAME_PREFIX);
|
|
19848
19965
|
}
|
|
@@ -19876,13 +19993,22 @@ function applyRegionToContext(ctx, region) {
|
|
|
19876
19993
|
return prevRegion;
|
|
19877
19994
|
}
|
|
19878
19995
|
function reserveHookSlot2(ctx) {
|
|
19996
|
+
if (ctx.dynamicHookSlotDepth && ctx.dynamicHookSlotDepth > 0) {
|
|
19997
|
+
return -1;
|
|
19998
|
+
}
|
|
19879
19999
|
const slot = ctx.nextHookSlot ?? HOOK_SLOT_BASE;
|
|
19880
20000
|
ctx.nextHookSlot = slot + 1;
|
|
19881
20001
|
return slot;
|
|
19882
20002
|
}
|
|
19883
20003
|
function expressionContainsJSX(expr) {
|
|
20004
|
+
if (Array.isArray(expr)) {
|
|
20005
|
+
return expr.some((item) => expressionContainsJSX(item));
|
|
20006
|
+
}
|
|
19884
20007
|
if (!expr || typeof expr !== "object") return false;
|
|
19885
20008
|
if (expr.kind === "JSXElement") return true;
|
|
20009
|
+
if (Array.isArray(expr.instructions)) {
|
|
20010
|
+
return expr.instructions.some((i) => expressionContainsJSX(i?.value ?? i));
|
|
20011
|
+
}
|
|
19886
20012
|
switch (expr.kind) {
|
|
19887
20013
|
case "CallExpression":
|
|
19888
20014
|
if (expressionContainsJSX(expr.callee)) return true;
|
|
@@ -19895,10 +20021,29 @@ function expressionContainsJSX(expr) {
|
|
|
19895
20021
|
return expressionContainsJSX(expr.test) || expressionContainsJSX(expr.consequent) || expressionContainsJSX(expr.alternate);
|
|
19896
20022
|
case "ArrowFunction":
|
|
19897
20023
|
return expressionContainsJSX(expr.body);
|
|
20024
|
+
case "FunctionExpression":
|
|
20025
|
+
if (Array.isArray(expr.body)) {
|
|
20026
|
+
return expr.body.some(
|
|
20027
|
+
(block) => block.instructions?.some((i) => expressionContainsJSX(i.value))
|
|
20028
|
+
);
|
|
20029
|
+
}
|
|
20030
|
+
return false;
|
|
19898
20031
|
default:
|
|
19899
20032
|
return false;
|
|
19900
20033
|
}
|
|
19901
20034
|
}
|
|
20035
|
+
function withNoMemoAndDynamicHooks(ctx, fn) {
|
|
20036
|
+
const prevNoMemo = ctx.noMemo;
|
|
20037
|
+
const prevDynamic = ctx.dynamicHookSlotDepth ?? 0;
|
|
20038
|
+
ctx.noMemo = true;
|
|
20039
|
+
ctx.dynamicHookSlotDepth = prevDynamic + 1;
|
|
20040
|
+
try {
|
|
20041
|
+
return fn();
|
|
20042
|
+
} finally {
|
|
20043
|
+
ctx.noMemo = prevNoMemo;
|
|
20044
|
+
ctx.dynamicHookSlotDepth = prevDynamic;
|
|
20045
|
+
}
|
|
20046
|
+
}
|
|
19902
20047
|
function functionContainsJSX(fn) {
|
|
19903
20048
|
for (const block of fn.blocks) {
|
|
19904
20049
|
for (const instr of block.instructions) {
|
|
@@ -20997,18 +21142,25 @@ function lowerTrackedExpression(expr, ctx) {
|
|
|
20997
21142
|
}
|
|
20998
21143
|
function lowerInstruction(instr, ctx) {
|
|
20999
21144
|
const { t: t2 } = ctx;
|
|
21145
|
+
const applyLoc = (stmt) => {
|
|
21146
|
+
if (!stmt) return stmt;
|
|
21147
|
+
const baseLoc = instr.loc ?? (instr.kind === "Assign" || instr.kind === "Expression" ? instr.value.loc : void 0);
|
|
21148
|
+
return setNodeLoc(stmt, baseLoc);
|
|
21149
|
+
};
|
|
21000
21150
|
if (instr.kind === "Assign") {
|
|
21001
21151
|
const baseName2 = deSSAVarName(instr.target.name);
|
|
21002
21152
|
const isFunctionDecl = instr.value.kind === "FunctionExpression" && (instr.declarationKind === "function" || !instr.declarationKind && instr.value.name === baseName2);
|
|
21003
21153
|
if (isFunctionDecl) {
|
|
21004
21154
|
const loweredFn = lowerExpression(instr.value, ctx);
|
|
21005
21155
|
if (t2.isFunctionExpression(loweredFn)) {
|
|
21006
|
-
return
|
|
21007
|
-
t2.
|
|
21008
|
-
|
|
21009
|
-
|
|
21010
|
-
|
|
21011
|
-
|
|
21156
|
+
return applyLoc(
|
|
21157
|
+
t2.functionDeclaration(
|
|
21158
|
+
t2.identifier(baseName2),
|
|
21159
|
+
loweredFn.params,
|
|
21160
|
+
loweredFn.body,
|
|
21161
|
+
loweredFn.generator ?? false,
|
|
21162
|
+
loweredFn.async ?? false
|
|
21163
|
+
)
|
|
21012
21164
|
);
|
|
21013
21165
|
}
|
|
21014
21166
|
}
|
|
@@ -21023,12 +21175,16 @@ function lowerInstruction(instr, ctx) {
|
|
|
21023
21175
|
ctx.memoVars?.add(baseName2);
|
|
21024
21176
|
}
|
|
21025
21177
|
if (declKind) {
|
|
21026
|
-
return
|
|
21027
|
-
t2.
|
|
21028
|
-
|
|
21178
|
+
return applyLoc(
|
|
21179
|
+
t2.variableDeclaration(declKind, [
|
|
21180
|
+
t2.variableDeclarator(t2.identifier(baseName2), hookMember.member)
|
|
21181
|
+
])
|
|
21182
|
+
);
|
|
21029
21183
|
}
|
|
21030
|
-
return
|
|
21031
|
-
t2.
|
|
21184
|
+
return applyLoc(
|
|
21185
|
+
t2.expressionStatement(
|
|
21186
|
+
t2.assignmentExpression("=", t2.identifier(baseName2), hookMember.member)
|
|
21187
|
+
)
|
|
21032
21188
|
);
|
|
21033
21189
|
}
|
|
21034
21190
|
if (instr.value.kind === "CallExpression" && instr.value.callee.kind === "Identifier" && isHookName(instr.value.callee.name)) {
|
|
@@ -21042,16 +21198,24 @@ function lowerInstruction(instr, ctx) {
|
|
|
21042
21198
|
}
|
|
21043
21199
|
}
|
|
21044
21200
|
if (ctx.signalVars?.has(baseName2)) {
|
|
21045
|
-
return
|
|
21046
|
-
t2.
|
|
21201
|
+
return applyLoc(
|
|
21202
|
+
t2.expressionStatement(
|
|
21203
|
+
t2.callExpression(t2.identifier(baseName2), [lowerTrackedExpression(instr.value, ctx)])
|
|
21204
|
+
)
|
|
21047
21205
|
);
|
|
21048
21206
|
}
|
|
21049
|
-
return
|
|
21050
|
-
t2.
|
|
21207
|
+
return applyLoc(
|
|
21208
|
+
t2.expressionStatement(
|
|
21209
|
+
t2.assignmentExpression(
|
|
21210
|
+
"=",
|
|
21211
|
+
t2.identifier(baseName2),
|
|
21212
|
+
lowerTrackedExpression(instr.value, ctx)
|
|
21213
|
+
)
|
|
21214
|
+
)
|
|
21051
21215
|
);
|
|
21052
21216
|
}
|
|
21053
21217
|
if (instr.kind === "Expression") {
|
|
21054
|
-
return t2.expressionStatement(lowerTrackedExpression(instr.value, ctx));
|
|
21218
|
+
return applyLoc(t2.expressionStatement(lowerTrackedExpression(instr.value, ctx)));
|
|
21055
21219
|
}
|
|
21056
21220
|
if (instr.kind === "Phi") {
|
|
21057
21221
|
return null;
|
|
@@ -21060,6 +21224,9 @@ function lowerInstruction(instr, ctx) {
|
|
|
21060
21224
|
}
|
|
21061
21225
|
function lowerTerminator(block, ctx) {
|
|
21062
21226
|
const { t: t2 } = ctx;
|
|
21227
|
+
const baseLoc = block.terminator.loc ?? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21228
|
+
block.terminator.argument?.loc;
|
|
21229
|
+
const applyLoc = (stmts) => stmts.map((stmt) => setNodeLoc(stmt, baseLoc));
|
|
21063
21230
|
switch (block.terminator.kind) {
|
|
21064
21231
|
case "Return": {
|
|
21065
21232
|
const prevRegion = ctx.currentRegion;
|
|
@@ -21072,14 +21239,14 @@ function lowerTerminator(block, ctx) {
|
|
|
21072
21239
|
}
|
|
21073
21240
|
ctx.inReturn = false;
|
|
21074
21241
|
ctx.currentRegion = prevRegion;
|
|
21075
|
-
return [t2.returnStatement(retExpr)];
|
|
21242
|
+
return applyLoc([t2.returnStatement(retExpr)]);
|
|
21076
21243
|
}
|
|
21077
21244
|
case "Throw":
|
|
21078
|
-
return [t2.throwStatement(lowerTrackedExpression(block.terminator.argument, ctx))];
|
|
21245
|
+
return applyLoc([t2.throwStatement(lowerTrackedExpression(block.terminator.argument, ctx))]);
|
|
21079
21246
|
case "Jump":
|
|
21080
|
-
return [t2.expressionStatement(t2.stringLiteral(`jump ${block.terminator.target}`))];
|
|
21247
|
+
return applyLoc([t2.expressionStatement(t2.stringLiteral(`jump ${block.terminator.target}`))]);
|
|
21081
21248
|
case "Branch":
|
|
21082
|
-
return [
|
|
21249
|
+
return applyLoc([
|
|
21083
21250
|
t2.ifStatement(
|
|
21084
21251
|
lowerTrackedExpression(block.terminator.test, ctx),
|
|
21085
21252
|
t2.blockStatement([
|
|
@@ -21089,9 +21256,9 @@ function lowerTerminator(block, ctx) {
|
|
|
21089
21256
|
t2.expressionStatement(t2.stringLiteral(`goto ${block.terminator.alternate}`))
|
|
21090
21257
|
])
|
|
21091
21258
|
)
|
|
21092
|
-
];
|
|
21259
|
+
]);
|
|
21093
21260
|
case "Switch":
|
|
21094
|
-
return [
|
|
21261
|
+
return applyLoc([
|
|
21095
21262
|
t2.switchStatement(
|
|
21096
21263
|
lowerTrackedExpression(block.terminator.discriminant, ctx),
|
|
21097
21264
|
block.terminator.cases.map(
|
|
@@ -21100,30 +21267,30 @@ function lowerTerminator(block, ctx) {
|
|
|
21100
21267
|
])
|
|
21101
21268
|
)
|
|
21102
21269
|
)
|
|
21103
|
-
];
|
|
21270
|
+
]);
|
|
21104
21271
|
case "ForOf": {
|
|
21105
21272
|
const term = block.terminator;
|
|
21106
21273
|
const varKind = term.variableKind ?? "const";
|
|
21107
21274
|
const leftPattern = term.pattern ? term.pattern : t2.identifier(term.variable);
|
|
21108
|
-
return [
|
|
21275
|
+
return applyLoc([
|
|
21109
21276
|
t2.forOfStatement(
|
|
21110
21277
|
t2.variableDeclaration(varKind, [t2.variableDeclarator(leftPattern)]),
|
|
21111
21278
|
lowerExpression(term.iterable, ctx),
|
|
21112
21279
|
t2.blockStatement([t2.expressionStatement(t2.stringLiteral(`body ${term.body}`))])
|
|
21113
21280
|
)
|
|
21114
|
-
];
|
|
21281
|
+
]);
|
|
21115
21282
|
}
|
|
21116
21283
|
case "ForIn": {
|
|
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.forInStatement(
|
|
21122
21289
|
t2.variableDeclaration(varKind, [t2.variableDeclarator(leftPattern)]),
|
|
21123
21290
|
lowerExpression(term.object, ctx),
|
|
21124
21291
|
t2.blockStatement([t2.expressionStatement(t2.stringLiteral(`body ${term.body}`))])
|
|
21125
21292
|
)
|
|
21126
|
-
];
|
|
21293
|
+
]);
|
|
21127
21294
|
}
|
|
21128
21295
|
case "Try": {
|
|
21129
21296
|
const term = block.terminator;
|
|
@@ -21139,20 +21306,20 @@ function lowerTerminator(block, ctx) {
|
|
|
21139
21306
|
const finallyBlock = term.finallyBlock !== void 0 ? t2.blockStatement([
|
|
21140
21307
|
t2.expressionStatement(t2.stringLiteral(`finally ${term.finallyBlock}`))
|
|
21141
21308
|
]) : null;
|
|
21142
|
-
return [t2.tryStatement(tryBlock, catchClause, finallyBlock)];
|
|
21309
|
+
return applyLoc([t2.tryStatement(tryBlock, catchClause, finallyBlock)]);
|
|
21143
21310
|
}
|
|
21144
21311
|
case "Unreachable":
|
|
21145
|
-
return [];
|
|
21312
|
+
return applyLoc([]);
|
|
21146
21313
|
case "Break":
|
|
21147
|
-
return [
|
|
21314
|
+
return applyLoc([
|
|
21148
21315
|
t2.breakStatement(block.terminator.label ? t2.identifier(block.terminator.label) : null)
|
|
21149
|
-
];
|
|
21316
|
+
]);
|
|
21150
21317
|
case "Continue":
|
|
21151
|
-
return [
|
|
21318
|
+
return applyLoc([
|
|
21152
21319
|
t2.continueStatement(block.terminator.label ? t2.identifier(block.terminator.label) : null)
|
|
21153
|
-
];
|
|
21320
|
+
]);
|
|
21154
21321
|
default:
|
|
21155
|
-
return [];
|
|
21322
|
+
return applyLoc([]);
|
|
21156
21323
|
}
|
|
21157
21324
|
}
|
|
21158
21325
|
function attachHelperImports(ctx, body, t2) {
|
|
@@ -21291,12 +21458,12 @@ function lowerExpression(expr, ctx, isAssigned = false) {
|
|
|
21291
21458
|
}
|
|
21292
21459
|
ctx.expressionDepth = depth;
|
|
21293
21460
|
try {
|
|
21294
|
-
return lowerExpressionImpl(expr, ctx, isAssigned);
|
|
21461
|
+
return setNodeLoc(lowerExpressionImpl(expr, ctx, isAssigned), expr.loc);
|
|
21295
21462
|
} finally {
|
|
21296
21463
|
ctx.expressionDepth = depth - 1;
|
|
21297
21464
|
}
|
|
21298
21465
|
}
|
|
21299
|
-
function lowerExpressionImpl(expr, ctx,
|
|
21466
|
+
function lowerExpressionImpl(expr, ctx, _isAssigned = false) {
|
|
21300
21467
|
const { t: t2 } = ctx;
|
|
21301
21468
|
const mapParams = (params) => params.map((p) => t2.identifier(deSSAVarName(p.name)));
|
|
21302
21469
|
const withFunctionScope = (paramNames, fn) => {
|
|
@@ -21358,11 +21525,7 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21358
21525
|
};
|
|
21359
21526
|
const declared = new Set(paramIds.map((p) => p.name));
|
|
21360
21527
|
return lowerStructuredNodeWithoutRegions(structured, t2, ctx, declared);
|
|
21361
|
-
} catch
|
|
21362
|
-
console.log(
|
|
21363
|
-
"[DEBUG] Structurization failed, falling back to lowerBlocksToStatements via lowerInstruction",
|
|
21364
|
-
e
|
|
21365
|
-
);
|
|
21528
|
+
} catch {
|
|
21366
21529
|
return lowerBlocksToStatements(blocks);
|
|
21367
21530
|
}
|
|
21368
21531
|
};
|
|
@@ -21426,14 +21589,22 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21426
21589
|
const calleeIsMemoAccessor = !!calleeName && ctx.memoVars?.has(calleeName);
|
|
21427
21590
|
const calleeIsSignalLike = !!calleeName && (ctx.signalVars?.has(calleeName) || ctx.storeVars?.has(calleeName));
|
|
21428
21591
|
if (calleeIsMemoAccessor && !calleeIsSignalLike && expr.arguments.length > 0) {
|
|
21429
|
-
const
|
|
21430
|
-
return t2.callExpression(t2.callExpression(t2.identifier(calleeName), []),
|
|
21592
|
+
const loweredArgs2 = expr.arguments.map((a) => lowerExpression(a, ctx));
|
|
21593
|
+
return t2.callExpression(t2.callExpression(t2.identifier(calleeName), []), loweredArgs2);
|
|
21431
21594
|
}
|
|
21432
21595
|
const lowerCallee = () => isIIFE ? withNonReactiveScope(ctx, () => lowerExpression(expr.callee, ctx)) : lowerExpression(expr.callee, ctx);
|
|
21433
|
-
|
|
21434
|
-
|
|
21435
|
-
|
|
21436
|
-
|
|
21596
|
+
const isIteratingMethod = expr.callee.kind === "MemberExpression" && (expr.callee.property.kind === "Identifier" && ["map", "reduce", "forEach", "filter", "flatMap", "some", "every", "find"].includes(
|
|
21597
|
+
expr.callee.property.name
|
|
21598
|
+
) || expr.callee.property.kind === "Literal" && ["map", "reduce", "forEach", "filter", "flatMap", "some", "every", "find"].includes(
|
|
21599
|
+
String(expr.callee.property.value)
|
|
21600
|
+
));
|
|
21601
|
+
const loweredArgs = expr.arguments.map((a, idx) => {
|
|
21602
|
+
if (idx === 0 && isIteratingMethod && (a.kind === "ArrowFunction" || a.kind === "FunctionExpression")) {
|
|
21603
|
+
return withNoMemoAndDynamicHooks(ctx, () => lowerExpression(a, ctx));
|
|
21604
|
+
}
|
|
21605
|
+
return lowerExpression(a, ctx);
|
|
21606
|
+
});
|
|
21607
|
+
return t2.callExpression(lowerCallee(), loweredArgs);
|
|
21437
21608
|
}
|
|
21438
21609
|
case "MemberExpression":
|
|
21439
21610
|
if (matchesListKeyPattern(expr, ctx)) {
|
|
@@ -21533,12 +21704,10 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21533
21704
|
case "ArrowFunction": {
|
|
21534
21705
|
const paramIds = mapParams(expr.params);
|
|
21535
21706
|
const shadowed = new Set(expr.params.map((p) => deSSAVarName(p.name)));
|
|
21536
|
-
return
|
|
21537
|
-
|
|
21538
|
-
|
|
21539
|
-
|
|
21540
|
-
let fn;
|
|
21541
|
-
try {
|
|
21707
|
+
return withNonReactiveScope(
|
|
21708
|
+
ctx,
|
|
21709
|
+
() => withFunctionScope(shadowed, () => {
|
|
21710
|
+
let fn;
|
|
21542
21711
|
if (expr.isExpression && !Array.isArray(expr.body)) {
|
|
21543
21712
|
const { result: bodyExpr, cacheDeclarations } = withGetterCache(
|
|
21544
21713
|
ctx,
|
|
@@ -21566,12 +21735,8 @@ function lowerExpressionImpl(expr, ctx, isAssigned = false) {
|
|
|
21566
21735
|
}
|
|
21567
21736
|
fn.async = expr.isAsync ?? false;
|
|
21568
21737
|
return fn;
|
|
21569
|
-
}
|
|
21570
|
-
|
|
21571
|
-
ctx.nonReactiveScopeDepth = (ctx.nonReactiveScopeDepth ?? 0) - 1;
|
|
21572
|
-
}
|
|
21573
|
-
}
|
|
21574
|
-
});
|
|
21738
|
+
})
|
|
21739
|
+
);
|
|
21575
21740
|
}
|
|
21576
21741
|
case "FunctionExpression": {
|
|
21577
21742
|
const paramIds = mapParams(expr.params);
|
|
@@ -22290,15 +22455,6 @@ function isStaticValue(expr) {
|
|
|
22290
22455
|
if (!expr) return false;
|
|
22291
22456
|
return expr.kind === "Literal";
|
|
22292
22457
|
}
|
|
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
22458
|
function isLikelyTextExpression(expr, ctx) {
|
|
22303
22459
|
let ok = true;
|
|
22304
22460
|
const isReactiveIdentifier = (name) => {
|
|
@@ -22327,15 +22483,9 @@ function isLikelyTextExpression(expr, ctx) {
|
|
|
22327
22483
|
ok = false;
|
|
22328
22484
|
return;
|
|
22329
22485
|
case "CallExpression":
|
|
22330
|
-
case "OptionalCallExpression":
|
|
22331
|
-
|
|
22332
|
-
ok = false;
|
|
22333
|
-
return;
|
|
22334
|
-
}
|
|
22335
|
-
visit(node.callee, true);
|
|
22336
|
-
node.arguments.forEach((arg) => visit(arg));
|
|
22486
|
+
case "OptionalCallExpression":
|
|
22487
|
+
ok = false;
|
|
22337
22488
|
return;
|
|
22338
|
-
}
|
|
22339
22489
|
case "MemberExpression":
|
|
22340
22490
|
case "OptionalMemberExpression":
|
|
22341
22491
|
visit(node.object, true);
|
|
@@ -22767,16 +22917,28 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
22767
22917
|
t2.expressionStatement(lowerDomExpression(binding.expr, ctx, containingRegion))
|
|
22768
22918
|
);
|
|
22769
22919
|
} else if (binding.type === "text" && binding.expr) {
|
|
22770
|
-
ctx.helpersUsed.add("bindText");
|
|
22771
22920
|
const valueExpr = lowerDomExpression(binding.expr, ctx, containingRegion);
|
|
22772
|
-
|
|
22773
|
-
|
|
22774
|
-
|
|
22775
|
-
|
|
22776
|
-
t2.
|
|
22777
|
-
|
|
22778
|
-
|
|
22779
|
-
|
|
22921
|
+
if (isExpressionReactive(binding.expr, ctx)) {
|
|
22922
|
+
ctx.helpersUsed.add("bindText");
|
|
22923
|
+
statements.push(
|
|
22924
|
+
t2.expressionStatement(
|
|
22925
|
+
t2.callExpression(t2.identifier(RUNTIME_ALIASES.bindText), [
|
|
22926
|
+
targetId,
|
|
22927
|
+
t2.arrowFunctionExpression([], valueExpr)
|
|
22928
|
+
])
|
|
22929
|
+
)
|
|
22930
|
+
);
|
|
22931
|
+
} else {
|
|
22932
|
+
statements.push(
|
|
22933
|
+
t2.expressionStatement(
|
|
22934
|
+
t2.assignmentExpression(
|
|
22935
|
+
"=",
|
|
22936
|
+
t2.memberExpression(targetId, t2.identifier("data")),
|
|
22937
|
+
t2.callExpression(t2.identifier("String"), [valueExpr])
|
|
22938
|
+
)
|
|
22939
|
+
)
|
|
22940
|
+
);
|
|
22941
|
+
}
|
|
22780
22942
|
} else if (binding.type === "child" && binding.expr) {
|
|
22781
22943
|
emitHIRChildBinding(targetId, binding.expr, statements, ctx, containingRegion);
|
|
22782
22944
|
}
|
|
@@ -22790,7 +22952,12 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
22790
22952
|
t2.arrowFunctionExpression([], body)
|
|
22791
22953
|
];
|
|
22792
22954
|
if (ctx.isComponentFn) {
|
|
22793
|
-
|
|
22955
|
+
{
|
|
22956
|
+
const slot = reserveHookSlot2(ctx);
|
|
22957
|
+
if (slot >= 0) {
|
|
22958
|
+
memoArgs.push(t2.numericLiteral(slot));
|
|
22959
|
+
}
|
|
22960
|
+
}
|
|
22794
22961
|
}
|
|
22795
22962
|
return t2.callExpression(t2.callExpression(t2.identifier(RUNTIME_ALIASES.useMemo), memoArgs), []);
|
|
22796
22963
|
}
|
|
@@ -23085,8 +23252,13 @@ function getTrackedCallIdentifier(expr, ctx, itemParamName) {
|
|
|
23085
23252
|
}
|
|
23086
23253
|
return null;
|
|
23087
23254
|
}
|
|
23088
|
-
function rewriteSelectorExpression(expr, itemParamName, getSelectorId, ctx) {
|
|
23255
|
+
function rewriteSelectorExpression(expr, itemParamName, keyParamName, getSelectorId, ctx) {
|
|
23089
23256
|
const { t: t2 } = ctx;
|
|
23257
|
+
const usesParamIdentifier = (e) => {
|
|
23258
|
+
if (expressionUsesIdentifier(e, itemParamName, t2)) return true;
|
|
23259
|
+
if (keyParamName && expressionUsesIdentifier(e, keyParamName, t2)) return true;
|
|
23260
|
+
return false;
|
|
23261
|
+
};
|
|
23090
23262
|
if (t2.isBinaryExpression(expr) && (expr.operator === "===" || expr.operator === "==")) {
|
|
23091
23263
|
const leftTracked = getTrackedCallIdentifier(
|
|
23092
23264
|
expr.left,
|
|
@@ -23098,7 +23270,7 @@ function rewriteSelectorExpression(expr, itemParamName, getSelectorId, ctx) {
|
|
|
23098
23270
|
ctx,
|
|
23099
23271
|
itemParamName
|
|
23100
23272
|
);
|
|
23101
|
-
if (leftTracked &&
|
|
23273
|
+
if (leftTracked && usesParamIdentifier(expr.right)) {
|
|
23102
23274
|
return {
|
|
23103
23275
|
expr: t2.callExpression(getSelectorId(leftTracked), [
|
|
23104
23276
|
expr.right
|
|
@@ -23106,7 +23278,7 @@ function rewriteSelectorExpression(expr, itemParamName, getSelectorId, ctx) {
|
|
|
23106
23278
|
changed: true
|
|
23107
23279
|
};
|
|
23108
23280
|
}
|
|
23109
|
-
if (rightTracked &&
|
|
23281
|
+
if (rightTracked && usesParamIdentifier(expr.left)) {
|
|
23110
23282
|
return {
|
|
23111
23283
|
expr: t2.callExpression(getSelectorId(rightTracked), [
|
|
23112
23284
|
expr.left
|
|
@@ -23117,7 +23289,7 @@ function rewriteSelectorExpression(expr, itemParamName, getSelectorId, ctx) {
|
|
|
23117
23289
|
}
|
|
23118
23290
|
let changed = false;
|
|
23119
23291
|
const rewrite = (node) => {
|
|
23120
|
-
const result = rewriteSelectorExpression(node, itemParamName, getSelectorId, ctx);
|
|
23292
|
+
const result = rewriteSelectorExpression(node, itemParamName, keyParamName, getSelectorId, ctx);
|
|
23121
23293
|
if (result.changed) changed = true;
|
|
23122
23294
|
return result.expr;
|
|
23123
23295
|
};
|
|
@@ -23178,7 +23350,7 @@ function rewriteSelectorExpression(expr, itemParamName, getSelectorId, ctx) {
|
|
|
23178
23350
|
}
|
|
23179
23351
|
return { expr, changed };
|
|
23180
23352
|
}
|
|
23181
|
-
function applySelectorHoist(callbackExpr, itemParamName, statements, ctx) {
|
|
23353
|
+
function applySelectorHoist(callbackExpr, itemParamName, keyParamName, statements, ctx) {
|
|
23182
23354
|
const { t: t2 } = ctx;
|
|
23183
23355
|
if (!itemParamName) return;
|
|
23184
23356
|
if (!t2.isArrowFunctionExpression(callbackExpr) && !t2.isFunctionExpression(callbackExpr)) return;
|
|
@@ -23194,7 +23366,13 @@ function applySelectorHoist(callbackExpr, itemParamName, statements, ctx) {
|
|
|
23194
23366
|
if (t2.isBlockStatement(fn.body)) {
|
|
23195
23367
|
for (const stmt of fn.body.body) {
|
|
23196
23368
|
if (t2.isReturnStatement(stmt) && stmt.argument && t2.isExpression(stmt.argument)) {
|
|
23197
|
-
const result = rewriteSelectorExpression(
|
|
23369
|
+
const result = rewriteSelectorExpression(
|
|
23370
|
+
stmt.argument,
|
|
23371
|
+
itemParamName,
|
|
23372
|
+
keyParamName,
|
|
23373
|
+
getSelectorId,
|
|
23374
|
+
ctx
|
|
23375
|
+
);
|
|
23198
23376
|
if (result.changed) {
|
|
23199
23377
|
stmt.argument = result.expr;
|
|
23200
23378
|
}
|
|
@@ -23203,7 +23381,13 @@ function applySelectorHoist(callbackExpr, itemParamName, statements, ctx) {
|
|
|
23203
23381
|
return;
|
|
23204
23382
|
}
|
|
23205
23383
|
if (t2.isExpression(fn.body)) {
|
|
23206
|
-
const result = rewriteSelectorExpression(
|
|
23384
|
+
const result = rewriteSelectorExpression(
|
|
23385
|
+
fn.body,
|
|
23386
|
+
itemParamName,
|
|
23387
|
+
keyParamName,
|
|
23388
|
+
getSelectorId,
|
|
23389
|
+
ctx
|
|
23390
|
+
);
|
|
23207
23391
|
if (result.changed) {
|
|
23208
23392
|
fn.body = result.expr;
|
|
23209
23393
|
}
|
|
@@ -23345,12 +23529,16 @@ function emitListChild(parentId, markerId, expr, statements, ctx) {
|
|
|
23345
23529
|
const hoistedStatements = ctx.hoistedTemplateStatements;
|
|
23346
23530
|
ctx.hoistedTemplates = prevHoistedTemplates;
|
|
23347
23531
|
ctx.hoistedTemplateStatements = prevHoistedTemplateStatements;
|
|
23348
|
-
if (
|
|
23349
|
-
const firstParam = callbackExpr.params
|
|
23532
|
+
if (t2.isArrowFunctionExpression(callbackExpr) || t2.isFunctionExpression(callbackExpr)) {
|
|
23533
|
+
const [firstParam, secondParam] = callbackExpr.params;
|
|
23534
|
+
const overrides = {};
|
|
23350
23535
|
if (t2.isIdentifier(firstParam)) {
|
|
23351
|
-
|
|
23352
|
-
|
|
23353
|
-
|
|
23536
|
+
overrides[firstParam.name] = () => t2.callExpression(t2.identifier(firstParam.name), []);
|
|
23537
|
+
}
|
|
23538
|
+
if (t2.isIdentifier(secondParam)) {
|
|
23539
|
+
overrides[secondParam.name] = () => t2.callExpression(t2.identifier(secondParam.name), []);
|
|
23540
|
+
}
|
|
23541
|
+
if (Object.keys(overrides).length > 0) {
|
|
23354
23542
|
if (t2.isBlockStatement(callbackExpr.body)) {
|
|
23355
23543
|
replaceIdentifiersWithOverrides(callbackExpr.body, overrides, t2, callbackExpr.type, "body");
|
|
23356
23544
|
} else {
|
|
@@ -23363,7 +23551,14 @@ function emitListChild(parentId, markerId, expr, statements, ctx) {
|
|
|
23363
23551
|
const listId = genTemp(ctx, "list");
|
|
23364
23552
|
if (isKeyed) {
|
|
23365
23553
|
const itemParamName = t2.isArrowFunctionExpression(callbackExpr) || t2.isFunctionExpression(callbackExpr) ? t2.isIdentifier(callbackExpr.params[0]) ? callbackExpr.params[0].name : null : null;
|
|
23366
|
-
|
|
23554
|
+
const keyParamName = ctx.listKeyParamName ?? null;
|
|
23555
|
+
applySelectorHoist(
|
|
23556
|
+
callbackExpr,
|
|
23557
|
+
itemParamName,
|
|
23558
|
+
keyParamName,
|
|
23559
|
+
statements,
|
|
23560
|
+
ctx
|
|
23561
|
+
);
|
|
23367
23562
|
}
|
|
23368
23563
|
if (isKeyed && keyExpr) {
|
|
23369
23564
|
let keyExprAst = lowerExpression(keyExpr, ctx);
|
|
@@ -24244,10 +24439,9 @@ function lowerFunctionWithRegions(fn, ctx) {
|
|
|
24244
24439
|
}
|
|
24245
24440
|
}
|
|
24246
24441
|
const params = finalParams;
|
|
24247
|
-
const funcDecl =
|
|
24248
|
-
t2.identifier(fn.name ?? "fn"),
|
|
24249
|
-
|
|
24250
|
-
t2.blockStatement(statements)
|
|
24442
|
+
const funcDecl = setNodeLoc(
|
|
24443
|
+
t2.functionDeclaration(t2.identifier(fn.name ?? "fn"), params, t2.blockStatement(statements)),
|
|
24444
|
+
fn.loc
|
|
24251
24445
|
);
|
|
24252
24446
|
ctx.needsCtx = prevNeedsCtx;
|
|
24253
24447
|
ctx.shadowedNames = prevShadowed;
|
|
@@ -24336,10 +24530,44 @@ function isInsideNestedFunction(path) {
|
|
|
24336
24530
|
function isInsideJSX(path) {
|
|
24337
24531
|
return !!path.findParent((p) => p.isJSXElement?.() || p.isJSXFragment?.());
|
|
24338
24532
|
}
|
|
24339
|
-
function
|
|
24340
|
-
if (!
|
|
24533
|
+
function parseSuppressionCodes(raw) {
|
|
24534
|
+
if (!raw) return void 0;
|
|
24535
|
+
const codes = raw.split(/[,\s]+/).map((c) => c.trim()).filter(Boolean);
|
|
24536
|
+
return codes.length > 0 ? new Set(codes) : void 0;
|
|
24537
|
+
}
|
|
24538
|
+
function parseSuppressions(comments) {
|
|
24539
|
+
if (!comments) return [];
|
|
24540
|
+
const suppressions = [];
|
|
24541
|
+
for (const comment of comments) {
|
|
24542
|
+
const match = comment.value.match(/fict-ignore(-next-line)?(?:\s+(.+))?/i);
|
|
24543
|
+
if (!match || !comment.loc) continue;
|
|
24544
|
+
suppressions.push({
|
|
24545
|
+
line: comment.loc.start.line,
|
|
24546
|
+
nextLine: !!match[1],
|
|
24547
|
+
codes: parseSuppressionCodes(match[2])
|
|
24548
|
+
});
|
|
24549
|
+
}
|
|
24550
|
+
return suppressions;
|
|
24551
|
+
}
|
|
24552
|
+
function shouldSuppressWarning(suppressions, code, line) {
|
|
24553
|
+
return suppressions.some((entry) => {
|
|
24554
|
+
const targetLine = entry.nextLine ? entry.line + 1 : entry.line;
|
|
24555
|
+
if (targetLine !== line) return false;
|
|
24556
|
+
if (!entry.codes || entry.codes.size === 0) return true;
|
|
24557
|
+
return entry.codes.has(code);
|
|
24558
|
+
});
|
|
24559
|
+
}
|
|
24560
|
+
function createWarningDispatcher(onWarn, suppressions) {
|
|
24561
|
+
if (!onWarn) return () => {
|
|
24562
|
+
};
|
|
24563
|
+
return (warning) => {
|
|
24564
|
+
if (shouldSuppressWarning(suppressions, warning.code, warning.line)) return;
|
|
24565
|
+
onWarn(warning);
|
|
24566
|
+
};
|
|
24567
|
+
}
|
|
24568
|
+
function emitWarning(node, code, message, warn, fileName) {
|
|
24341
24569
|
const loc = node.loc?.start;
|
|
24342
|
-
|
|
24570
|
+
warn({
|
|
24343
24571
|
code,
|
|
24344
24572
|
message,
|
|
24345
24573
|
fileName,
|
|
@@ -24427,8 +24655,7 @@ function isDynamicPropertyAccess(node, t2) {
|
|
|
24427
24655
|
if (!node.computed) return false;
|
|
24428
24656
|
return !(t2.isStringLiteral(node.property) || t2.isNumericLiteral(node.property));
|
|
24429
24657
|
}
|
|
24430
|
-
function runWarningPass(programPath, stateVars, derivedVars,
|
|
24431
|
-
const fileName = programPath.hub?.file?.opts?.filename || "<unknown>";
|
|
24658
|
+
function runWarningPass(programPath, stateVars, derivedVars, warn, fileName, t2) {
|
|
24432
24659
|
const isStateRoot = (expr) => {
|
|
24433
24660
|
const root = getRootIdentifier(expr, t2);
|
|
24434
24661
|
return !!(root && stateVars.has(root.name));
|
|
@@ -24444,7 +24671,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24444
24671
|
path.node,
|
|
24445
24672
|
"FICT-M",
|
|
24446
24673
|
"Direct mutation of nested property detected; use immutable update or $store helpers",
|
|
24447
|
-
|
|
24674
|
+
warn,
|
|
24448
24675
|
fileName
|
|
24449
24676
|
);
|
|
24450
24677
|
if (isDynamicPropertyAccess(left, t2)) {
|
|
@@ -24452,7 +24679,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24452
24679
|
path.node,
|
|
24453
24680
|
"FICT-H",
|
|
24454
24681
|
"Dynamic property access widens dependency tracking",
|
|
24455
|
-
|
|
24682
|
+
warn,
|
|
24456
24683
|
fileName
|
|
24457
24684
|
);
|
|
24458
24685
|
}
|
|
@@ -24467,7 +24694,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24467
24694
|
path.node,
|
|
24468
24695
|
"FICT-M",
|
|
24469
24696
|
"Direct mutation of nested property detected; use immutable update or $store helpers",
|
|
24470
|
-
|
|
24697
|
+
warn,
|
|
24471
24698
|
fileName
|
|
24472
24699
|
);
|
|
24473
24700
|
if (isDynamicPropertyAccess(arg, t2)) {
|
|
@@ -24475,7 +24702,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24475
24702
|
path.node,
|
|
24476
24703
|
"FICT-H",
|
|
24477
24704
|
"Dynamic property access widens dependency tracking",
|
|
24478
|
-
|
|
24705
|
+
warn,
|
|
24479
24706
|
fileName
|
|
24480
24707
|
);
|
|
24481
24708
|
}
|
|
@@ -24491,7 +24718,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24491
24718
|
path.node,
|
|
24492
24719
|
"FICT-H",
|
|
24493
24720
|
"Dynamic property access widens dependency tracking",
|
|
24494
|
-
|
|
24721
|
+
warn,
|
|
24495
24722
|
fileName
|
|
24496
24723
|
);
|
|
24497
24724
|
}
|
|
@@ -24520,7 +24747,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24520
24747
|
path.node,
|
|
24521
24748
|
"FICT-R005",
|
|
24522
24749
|
`Function captures reactive variable(s): ${Array.from(captured).join(", ")}. Pass them as parameters or memoize explicitly to avoid hidden dependencies.`,
|
|
24523
|
-
|
|
24750
|
+
warn,
|
|
24524
24751
|
fileName
|
|
24525
24752
|
);
|
|
24526
24753
|
}
|
|
@@ -24551,7 +24778,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24551
24778
|
path.node,
|
|
24552
24779
|
"FICT-E001",
|
|
24553
24780
|
"Effect has no reactive reads; it will run once. Consider removing $effect or adding dependencies.",
|
|
24554
|
-
|
|
24781
|
+
warn,
|
|
24555
24782
|
fileName
|
|
24556
24783
|
);
|
|
24557
24784
|
}
|
|
@@ -24577,7 +24804,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24577
24804
|
arg,
|
|
24578
24805
|
"FICT-H",
|
|
24579
24806
|
"State value passed to unknown function (black box); dependency tracking may be imprecise",
|
|
24580
|
-
|
|
24807
|
+
warn,
|
|
24581
24808
|
fileName
|
|
24582
24809
|
);
|
|
24583
24810
|
break;
|
|
@@ -24593,7 +24820,7 @@ function runWarningPass(programPath, stateVars, derivedVars, options, t2) {
|
|
|
24593
24820
|
path.node,
|
|
24594
24821
|
"FICT-H",
|
|
24595
24822
|
"Dynamic property access widens dependency tracking",
|
|
24596
|
-
|
|
24823
|
+
warn,
|
|
24597
24824
|
fileName
|
|
24598
24825
|
);
|
|
24599
24826
|
}
|
|
@@ -24643,6 +24870,10 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24643
24870
|
Program: {
|
|
24644
24871
|
exit(path) {
|
|
24645
24872
|
const fileName = path.hub?.file?.opts?.filename || "<unknown>";
|
|
24873
|
+
const comments = path.hub?.file?.ast?.comments || [];
|
|
24874
|
+
const suppressions = parseSuppressions(comments);
|
|
24875
|
+
const warn = createWarningDispatcher(options.onWarn, suppressions);
|
|
24876
|
+
const optionsWithWarnings = { ...options, onWarn: warn };
|
|
24646
24877
|
const isHookName2 = (name) => !!name && /^use[A-Z]/.test(name);
|
|
24647
24878
|
const getFunctionName = (fnPath) => {
|
|
24648
24879
|
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 +24892,75 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24661
24892
|
return name && isComponentName(name) || isHookName2(name) || functionHasJSX(fnPath) || functionUsesStateLike(fnPath, t2);
|
|
24662
24893
|
};
|
|
24663
24894
|
const memoHasSideEffects = (fn) => {
|
|
24895
|
+
const pureCalls = new Set(
|
|
24896
|
+
Array.from(SAFE_FUNCTIONS).filter(
|
|
24897
|
+
(name) => !name.startsWith("console.") && name !== "Math.random"
|
|
24898
|
+
)
|
|
24899
|
+
);
|
|
24900
|
+
const effectfulCalls = /* @__PURE__ */ new Set([
|
|
24901
|
+
"$effect",
|
|
24902
|
+
"render",
|
|
24903
|
+
"fetch",
|
|
24904
|
+
"setTimeout",
|
|
24905
|
+
"setInterval",
|
|
24906
|
+
"clearTimeout",
|
|
24907
|
+
"clearInterval",
|
|
24908
|
+
"requestAnimationFrame",
|
|
24909
|
+
"cancelAnimationFrame"
|
|
24910
|
+
]);
|
|
24911
|
+
const getCalleeName = (callee) => {
|
|
24912
|
+
if (t2.isIdentifier(callee)) return callee.name;
|
|
24913
|
+
if (t2.isMemberExpression(callee) && !callee.computed && t2.isIdentifier(callee.property) && t2.isIdentifier(callee.object)) {
|
|
24914
|
+
return `${callee.object.name}.${callee.property.name}`;
|
|
24915
|
+
}
|
|
24916
|
+
return null;
|
|
24917
|
+
};
|
|
24918
|
+
const mutatingMemberProps = /* @__PURE__ */ new Set([
|
|
24919
|
+
"push",
|
|
24920
|
+
"pop",
|
|
24921
|
+
"splice",
|
|
24922
|
+
"shift",
|
|
24923
|
+
"unshift",
|
|
24924
|
+
"sort",
|
|
24925
|
+
"reverse",
|
|
24926
|
+
"set",
|
|
24927
|
+
"add",
|
|
24928
|
+
"delete",
|
|
24929
|
+
"append",
|
|
24930
|
+
"appendChild",
|
|
24931
|
+
"remove",
|
|
24932
|
+
"removeChild",
|
|
24933
|
+
"setAttribute",
|
|
24934
|
+
"dispatchEvent",
|
|
24935
|
+
"replaceChildren",
|
|
24936
|
+
"replaceWith"
|
|
24937
|
+
]);
|
|
24938
|
+
const isEffectfulCall = (node) => {
|
|
24939
|
+
const name = getCalleeName(node.callee);
|
|
24940
|
+
if (!name) return true;
|
|
24941
|
+
if (pureCalls.has(name)) return false;
|
|
24942
|
+
if (effectfulCalls.has(name)) return true;
|
|
24943
|
+
if (name.startsWith("console.") || name.startsWith("document.") || name.startsWith("window.")) {
|
|
24944
|
+
return true;
|
|
24945
|
+
}
|
|
24946
|
+
if (t2.isMemberExpression(node.callee) && !node.callee.computed && t2.isIdentifier(node.callee.property)) {
|
|
24947
|
+
const prop = node.callee.property.name;
|
|
24948
|
+
if (mutatingMemberProps.has(prop)) return true;
|
|
24949
|
+
if (t2.isIdentifier(node.callee.object) && (node.callee.object.name === "document" || node.callee.object.name === "window")) {
|
|
24950
|
+
return true;
|
|
24951
|
+
}
|
|
24952
|
+
}
|
|
24953
|
+
return false;
|
|
24954
|
+
};
|
|
24664
24955
|
const checkNode = (node) => {
|
|
24665
24956
|
if (!node) return false;
|
|
24666
24957
|
if (t2.isAssignmentExpression(node) || t2.isUpdateExpression(node) || t2.isThrowStatement(node) || t2.isNewExpression(node)) {
|
|
24667
24958
|
return true;
|
|
24668
24959
|
}
|
|
24669
|
-
if (t2.isCallExpression(node) && (
|
|
24960
|
+
if (t2.isCallExpression(node) && isEffectfulCall(node)) {
|
|
24670
24961
|
return true;
|
|
24671
24962
|
}
|
|
24963
|
+
if (t2.isAwaitExpression(node)) return true;
|
|
24672
24964
|
if (t2.isExpressionStatement(node)) return checkNode(node.expression);
|
|
24673
24965
|
if (t2.isBlockStatement(node)) return node.body.some((stmt) => checkNode(stmt));
|
|
24674
24966
|
if (t2.isReturnStatement(node)) return checkNode(node.argument);
|
|
@@ -24692,7 +24984,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24692
24984
|
fnPath.node,
|
|
24693
24985
|
"FICT-C004",
|
|
24694
24986
|
"Component has no return statement and will render nothing.",
|
|
24695
|
-
|
|
24987
|
+
warn,
|
|
24696
24988
|
fileName
|
|
24697
24989
|
);
|
|
24698
24990
|
},
|
|
@@ -24710,7 +25002,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24710
25002
|
init,
|
|
24711
25003
|
"FICT-C004",
|
|
24712
25004
|
"Component has no return statement and will render nothing.",
|
|
24713
|
-
|
|
25005
|
+
warn,
|
|
24714
25006
|
fileName
|
|
24715
25007
|
);
|
|
24716
25008
|
}
|
|
@@ -24760,7 +25052,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24760
25052
|
}
|
|
24761
25053
|
}
|
|
24762
25054
|
if (hasKey || hasUnknownSpread) return;
|
|
24763
|
-
|
|
25055
|
+
warn({
|
|
24764
25056
|
code: "FICT-J002",
|
|
24765
25057
|
message: "Missing key prop in list rendering.",
|
|
24766
25058
|
fileName,
|
|
@@ -24831,7 +25123,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24831
25123
|
fnPath.node,
|
|
24832
25124
|
"FICT-C003",
|
|
24833
25125
|
"Components should not be defined inside other components. Move this definition to module scope to preserve identity and performance.",
|
|
24834
|
-
|
|
25126
|
+
warn,
|
|
24835
25127
|
fileName
|
|
24836
25128
|
);
|
|
24837
25129
|
},
|
|
@@ -24876,7 +25168,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24876
25168
|
callPath.node,
|
|
24877
25169
|
"FICT-R004",
|
|
24878
25170
|
"Reactive creation inside non-JSX control flow will not auto-dispose; wrap it in createScope/runInScope or move it into JSX-managed regions.",
|
|
24879
|
-
|
|
25171
|
+
warn,
|
|
24880
25172
|
fileName
|
|
24881
25173
|
);
|
|
24882
25174
|
}
|
|
@@ -24911,7 +25203,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24911
25203
|
callPath.node.arguments.forEach((arg) => {
|
|
24912
25204
|
if (t2.isIdentifier(arg) && stateVars.has(arg.name) && (!calleeId || !allowedStateCallees.has(calleeId))) {
|
|
24913
25205
|
const loc = arg.loc?.start ?? callPath.node.loc?.start;
|
|
24914
|
-
|
|
25206
|
+
warn({
|
|
24915
25207
|
code: "FICT-S002",
|
|
24916
25208
|
message: "State variable is passed as an argument; this passes a value snapshot and may escape component scope.",
|
|
24917
25209
|
fileName,
|
|
@@ -24924,7 +25216,7 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
24924
25216
|
const firstArg = callPath.node.arguments[0];
|
|
24925
25217
|
if (firstArg && (t2.isArrowFunctionExpression(firstArg) || t2.isFunctionExpression(firstArg)) && memoHasSideEffects(firstArg)) {
|
|
24926
25218
|
const loc = firstArg.loc?.start ?? callPath.node.loc?.start;
|
|
24927
|
-
|
|
25219
|
+
warn({
|
|
24928
25220
|
code: "FICT-M003",
|
|
24929
25221
|
message: "Memo should not contain side effects.",
|
|
24930
25222
|
fileName,
|
|
@@ -25029,10 +25321,10 @@ function createHIREntrypointVisitor(t2, options) {
|
|
|
25029
25321
|
}
|
|
25030
25322
|
});
|
|
25031
25323
|
}
|
|
25032
|
-
runWarningPass(path, stateVars, derivedVars,
|
|
25324
|
+
runWarningPass(path, stateVars, derivedVars, warn, fileName, t2);
|
|
25033
25325
|
const fileAst = t2.file(path.node);
|
|
25034
25326
|
const hir = buildHIR(fileAst);
|
|
25035
|
-
const lowered = lowerHIRWithRegions(hir, t2,
|
|
25327
|
+
const lowered = lowerHIRWithRegions(hir, t2, optionsWithWarnings);
|
|
25036
25328
|
path.node.body = lowered.program.body;
|
|
25037
25329
|
path.node.directives = lowered.program.directives;
|
|
25038
25330
|
if (!process.env.FICT_SKIP_SCOPE_CRAWL) {
|