@fictjs/compiler 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +876 -64
- package/dist/index.d.cts +393 -1
- package/dist/index.d.ts +393 -1
- package/dist/index.js +874 -64
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -3065,7 +3065,7 @@ var require_identifier = __commonJS({
|
|
|
3065
3065
|
value: true
|
|
3066
3066
|
});
|
|
3067
3067
|
exports2.isIdentifierChar = isIdentifierChar;
|
|
3068
|
-
exports2.isIdentifierName =
|
|
3068
|
+
exports2.isIdentifierName = isIdentifierName2;
|
|
3069
3069
|
exports2.isIdentifierStart = isIdentifierStart;
|
|
3070
3070
|
var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088F\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5C\u0C5D\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDC-\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C8A\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7DC\uA7F1-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC";
|
|
3071
3071
|
var nonASCIIidentifierChars = "\xB7\u0300-\u036F\u0387\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u0897-\u089F\u08CA-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B55-\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C04\u0C3C\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0CF3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D81-\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EBC\u0EC8-\u0ECE\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u180F-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19D0-\u19DA\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1ABF-\u1ADD\u1AE0-\u1AEB\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DFF\u200C\u200D\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\u30FB\uA620-\uA629\uA66F\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA82C\uA880\uA881\uA8B4-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F1\uA8FF-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F\uFF65";
|
|
@@ -3106,7 +3106,7 @@ var require_identifier = __commonJS({
|
|
|
3106
3106
|
}
|
|
3107
3107
|
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
|
|
3108
3108
|
}
|
|
3109
|
-
function
|
|
3109
|
+
function isIdentifierName2(name) {
|
|
3110
3110
|
let isFirst = true;
|
|
3111
3111
|
for (let i = 0; i < name.length; i++) {
|
|
3112
3112
|
let cp = name.charCodeAt(i);
|
|
@@ -14098,9 +14098,11 @@ var require_lib3 = __commonJS({
|
|
|
14098
14098
|
// src/index.ts
|
|
14099
14099
|
var index_exports = {};
|
|
14100
14100
|
__export(index_exports, {
|
|
14101
|
+
analyzeFictFile: () => analyzeFictFile,
|
|
14101
14102
|
clearModuleMetadata: () => clearModuleMetadata,
|
|
14102
14103
|
createFictPlugin: () => createFictPlugin,
|
|
14103
14104
|
default: () => index_default,
|
|
14105
|
+
inferTraceMarkersForComponent: () => inferTraceMarkersForComponent,
|
|
14104
14106
|
resolveModuleMetadata: () => resolveModuleMetadata,
|
|
14105
14107
|
setModuleMetadata: () => setModuleMetadata
|
|
14106
14108
|
});
|
|
@@ -17088,6 +17090,37 @@ function clearModuleMetadata(options) {
|
|
|
17088
17090
|
}
|
|
17089
17091
|
|
|
17090
17092
|
// src/validation.ts
|
|
17093
|
+
var DiagnosticCode = /* @__PURE__ */ ((DiagnosticCode2) => {
|
|
17094
|
+
DiagnosticCode2["FICT_P001"] = "FICT-P001";
|
|
17095
|
+
DiagnosticCode2["FICT_P002"] = "FICT-P002";
|
|
17096
|
+
DiagnosticCode2["FICT_P003"] = "FICT-P003";
|
|
17097
|
+
DiagnosticCode2["FICT_P004"] = "FICT-P004";
|
|
17098
|
+
DiagnosticCode2["FICT_P005"] = "FICT-P005";
|
|
17099
|
+
DiagnosticCode2["FICT_S001"] = "FICT-S001";
|
|
17100
|
+
DiagnosticCode2["FICT_S002"] = "FICT-S002";
|
|
17101
|
+
DiagnosticCode2["FICT_E001"] = "FICT-E001";
|
|
17102
|
+
DiagnosticCode2["FICT_E002"] = "FICT-E002";
|
|
17103
|
+
DiagnosticCode2["FICT_E003"] = "FICT-E003";
|
|
17104
|
+
DiagnosticCode2["FICT_M001"] = "FICT-M001";
|
|
17105
|
+
DiagnosticCode2["FICT_M002"] = "FICT-M002";
|
|
17106
|
+
DiagnosticCode2["FICT_M003"] = "FICT-M003";
|
|
17107
|
+
DiagnosticCode2["FICT_C001"] = "FICT-C001";
|
|
17108
|
+
DiagnosticCode2["FICT_C002"] = "FICT-C002";
|
|
17109
|
+
DiagnosticCode2["FICT_C003"] = "FICT-C003";
|
|
17110
|
+
DiagnosticCode2["FICT_C004"] = "FICT-C004";
|
|
17111
|
+
DiagnosticCode2["FICT_J001"] = "FICT-J001";
|
|
17112
|
+
DiagnosticCode2["FICT_J002"] = "FICT-J002";
|
|
17113
|
+
DiagnosticCode2["FICT_J003"] = "FICT-J003";
|
|
17114
|
+
DiagnosticCode2["FICT_R001"] = "FICT-R001";
|
|
17115
|
+
DiagnosticCode2["FICT_R002"] = "FICT-R002";
|
|
17116
|
+
DiagnosticCode2["FICT_R003"] = "FICT-R003";
|
|
17117
|
+
DiagnosticCode2["FICT_R004"] = "FICT-R004";
|
|
17118
|
+
DiagnosticCode2["FICT_R005"] = "FICT-R005";
|
|
17119
|
+
DiagnosticCode2["FICT_X001"] = "FICT-X001";
|
|
17120
|
+
DiagnosticCode2["FICT_X002"] = "FICT-X002";
|
|
17121
|
+
DiagnosticCode2["FICT_X003"] = "FICT-X003";
|
|
17122
|
+
return DiagnosticCode2;
|
|
17123
|
+
})(DiagnosticCode || {});
|
|
17091
17124
|
var DiagnosticMessages = {
|
|
17092
17125
|
["FICT-P001" /* FICT_P001 */]: "Props destructuring falls back to non-reactive binding.",
|
|
17093
17126
|
["FICT-P002" /* FICT_P002 */]: "Array rest in props destructuring falls back to non-reactive binding.",
|
|
@@ -17175,6 +17208,16 @@ function reportDiagnostic(ctx, code, node, context) {
|
|
|
17175
17208
|
});
|
|
17176
17209
|
}
|
|
17177
17210
|
}
|
|
17211
|
+
function getAllDiagnosticCodes() {
|
|
17212
|
+
return Object.values(DiagnosticCode);
|
|
17213
|
+
}
|
|
17214
|
+
function getDiagnosticInfo(code) {
|
|
17215
|
+
return {
|
|
17216
|
+
code,
|
|
17217
|
+
severity: DiagnosticSeverities[code],
|
|
17218
|
+
message: DiagnosticMessages[code]
|
|
17219
|
+
};
|
|
17220
|
+
}
|
|
17178
17221
|
|
|
17179
17222
|
// src/ir/ssa.ts
|
|
17180
17223
|
function enterSSA(program) {
|
|
@@ -18895,6 +18938,22 @@ function structurizeBlockUntilJoin(ctx, blockId, joinBlock) {
|
|
|
18895
18938
|
if (branchNode) nodes.push(branchNode);
|
|
18896
18939
|
break;
|
|
18897
18940
|
}
|
|
18941
|
+
case "Switch": {
|
|
18942
|
+
nodes.push(structurizeSwitch(ctx, block, term));
|
|
18943
|
+
break;
|
|
18944
|
+
}
|
|
18945
|
+
case "ForOf": {
|
|
18946
|
+
nodes.push(structurizeForOf(ctx, block, term));
|
|
18947
|
+
break;
|
|
18948
|
+
}
|
|
18949
|
+
case "ForIn": {
|
|
18950
|
+
nodes.push(structurizeForIn(ctx, block, term));
|
|
18951
|
+
break;
|
|
18952
|
+
}
|
|
18953
|
+
case "Try": {
|
|
18954
|
+
nodes.push(structurizeTry(ctx, block, term));
|
|
18955
|
+
break;
|
|
18956
|
+
}
|
|
18898
18957
|
case "Break":
|
|
18899
18958
|
nodes.push({ kind: "break", label: term.label });
|
|
18900
18959
|
break;
|
|
@@ -19029,7 +19088,9 @@ function isSwitchCaseTerminated(node) {
|
|
|
19029
19088
|
}
|
|
19030
19089
|
}
|
|
19031
19090
|
function structurizeForOf(ctx, block, term) {
|
|
19091
|
+
ctx.reservedBlocks.add(term.exit);
|
|
19032
19092
|
const body = structurizeBlock(ctx, term.body);
|
|
19093
|
+
ctx.reservedBlocks.delete(term.exit);
|
|
19033
19094
|
const exit = !ctx.emitted.has(term.exit) ? structurizeBlock(ctx, term.exit) : null;
|
|
19034
19095
|
const forOfNode = {
|
|
19035
19096
|
kind: "forOf",
|
|
@@ -19045,7 +19106,9 @@ function structurizeForOf(ctx, block, term) {
|
|
|
19045
19106
|
return forOfNode;
|
|
19046
19107
|
}
|
|
19047
19108
|
function structurizeForIn(ctx, block, term) {
|
|
19109
|
+
ctx.reservedBlocks.add(term.exit);
|
|
19048
19110
|
const body = structurizeBlock(ctx, term.body);
|
|
19111
|
+
ctx.reservedBlocks.delete(term.exit);
|
|
19049
19112
|
const exit = !ctx.emitted.has(term.exit) ? structurizeBlock(ctx, term.exit) : null;
|
|
19050
19113
|
const forInNode = {
|
|
19051
19114
|
kind: "forIn",
|
|
@@ -24267,34 +24330,138 @@ function extractKeyFromAttributes(attributes) {
|
|
|
24267
24330
|
}
|
|
24268
24331
|
return void 0;
|
|
24269
24332
|
}
|
|
24333
|
+
function collectReturnedJSXFromExpression(expression, returned) {
|
|
24334
|
+
if (expression.kind === "JSXElement") {
|
|
24335
|
+
returned.push(expression);
|
|
24336
|
+
return;
|
|
24337
|
+
}
|
|
24338
|
+
if (expression.kind === "ConditionalExpression") {
|
|
24339
|
+
collectReturnedJSXFromExpression(expression.consequent, returned);
|
|
24340
|
+
collectReturnedJSXFromExpression(expression.alternate, returned);
|
|
24341
|
+
return;
|
|
24342
|
+
}
|
|
24343
|
+
if (expression.kind === "LogicalExpression") {
|
|
24344
|
+
collectReturnedJSXFromExpression(expression.left, returned);
|
|
24345
|
+
collectReturnedJSXFromExpression(expression.right, returned);
|
|
24346
|
+
return;
|
|
24347
|
+
}
|
|
24348
|
+
if (expression.kind === "SequenceExpression") {
|
|
24349
|
+
const tail = expression.expressions[expression.expressions.length - 1];
|
|
24350
|
+
if (tail) collectReturnedJSXFromExpression(tail, returned);
|
|
24351
|
+
}
|
|
24352
|
+
}
|
|
24353
|
+
function extractKeyExpressionFromReturnedExpression(expression) {
|
|
24354
|
+
if (expression.kind === "JSXElement") {
|
|
24355
|
+
return extractKeyFromAttributes(expression.attributes);
|
|
24356
|
+
}
|
|
24357
|
+
if (expression.kind === "ConditionalExpression") {
|
|
24358
|
+
const consequentKey = extractKeyExpressionFromReturnedExpression(expression.consequent);
|
|
24359
|
+
const alternateKey = extractKeyExpressionFromReturnedExpression(expression.alternate);
|
|
24360
|
+
if (!consequentKey || !alternateKey) return void 0;
|
|
24361
|
+
return {
|
|
24362
|
+
kind: "ConditionalExpression",
|
|
24363
|
+
test: expression.test,
|
|
24364
|
+
consequent: consequentKey,
|
|
24365
|
+
alternate: alternateKey,
|
|
24366
|
+
loc: expression.loc
|
|
24367
|
+
};
|
|
24368
|
+
}
|
|
24369
|
+
if (expression.kind === "SequenceExpression") {
|
|
24370
|
+
const tail = expression.expressions[expression.expressions.length - 1];
|
|
24371
|
+
return tail ? extractKeyExpressionFromReturnedExpression(tail) : void 0;
|
|
24372
|
+
}
|
|
24373
|
+
return void 0;
|
|
24374
|
+
}
|
|
24375
|
+
function getReturnedKeyExpressionsFromCallback(callback) {
|
|
24376
|
+
const returned = [];
|
|
24377
|
+
if (callback.kind === "ArrowFunction") {
|
|
24378
|
+
if (callback.isExpression && !Array.isArray(callback.body)) {
|
|
24379
|
+
const keyExpr = extractKeyExpressionFromReturnedExpression(callback.body);
|
|
24380
|
+
if (keyExpr) returned.push(keyExpr);
|
|
24381
|
+
return returned;
|
|
24382
|
+
}
|
|
24383
|
+
if (Array.isArray(callback.body)) {
|
|
24384
|
+
for (const block of callback.body) {
|
|
24385
|
+
const term = block.terminator;
|
|
24386
|
+
if (term.kind !== "Return" || !term.argument) continue;
|
|
24387
|
+
const keyExpr = extractKeyExpressionFromReturnedExpression(term.argument);
|
|
24388
|
+
if (keyExpr) returned.push(keyExpr);
|
|
24389
|
+
}
|
|
24390
|
+
}
|
|
24391
|
+
return returned;
|
|
24392
|
+
}
|
|
24393
|
+
if (callback.kind === "FunctionExpression") {
|
|
24394
|
+
for (const block of callback.body ?? []) {
|
|
24395
|
+
const term = block.terminator;
|
|
24396
|
+
if (term.kind !== "Return" || !term.argument) continue;
|
|
24397
|
+
const keyExpr = extractKeyExpressionFromReturnedExpression(term.argument);
|
|
24398
|
+
if (keyExpr) returned.push(keyExpr);
|
|
24399
|
+
}
|
|
24400
|
+
}
|
|
24401
|
+
return returned;
|
|
24402
|
+
}
|
|
24270
24403
|
function getReturnedJSXFromCallback(callback) {
|
|
24404
|
+
const returned = [];
|
|
24271
24405
|
if (callback.kind === "ArrowFunction") {
|
|
24272
|
-
if (callback.isExpression && !Array.isArray(callback.body)
|
|
24273
|
-
|
|
24406
|
+
if (callback.isExpression && !Array.isArray(callback.body)) {
|
|
24407
|
+
collectReturnedJSXFromExpression(callback.body, returned);
|
|
24408
|
+
return returned;
|
|
24274
24409
|
}
|
|
24275
24410
|
if (Array.isArray(callback.body)) {
|
|
24276
24411
|
for (const block of callback.body) {
|
|
24277
24412
|
const term = block.terminator;
|
|
24278
|
-
if (term.kind === "Return" && term.argument
|
|
24279
|
-
|
|
24413
|
+
if (term.kind === "Return" && term.argument) {
|
|
24414
|
+
collectReturnedJSXFromExpression(term.argument, returned);
|
|
24280
24415
|
}
|
|
24281
24416
|
}
|
|
24282
24417
|
}
|
|
24418
|
+
return returned;
|
|
24283
24419
|
}
|
|
24284
24420
|
if (callback.kind === "FunctionExpression") {
|
|
24285
24421
|
for (const block of callback.body ?? []) {
|
|
24286
24422
|
const term = block.terminator;
|
|
24287
|
-
if (term.kind === "Return" && term.argument
|
|
24288
|
-
|
|
24423
|
+
if (term.kind === "Return" && term.argument) {
|
|
24424
|
+
collectReturnedJSXFromExpression(term.argument, returned);
|
|
24289
24425
|
}
|
|
24290
24426
|
}
|
|
24291
24427
|
}
|
|
24292
|
-
return
|
|
24428
|
+
return returned;
|
|
24429
|
+
}
|
|
24430
|
+
function keyExpressionSignature(expression) {
|
|
24431
|
+
try {
|
|
24432
|
+
return JSON.stringify(expression, (key, value) => {
|
|
24433
|
+
if (key === "loc") return void 0;
|
|
24434
|
+
if (typeof value === "bigint") return `__bigint:${value.toString()}`;
|
|
24435
|
+
return value;
|
|
24436
|
+
}) ?? "";
|
|
24437
|
+
} catch {
|
|
24438
|
+
return "";
|
|
24439
|
+
}
|
|
24293
24440
|
}
|
|
24294
24441
|
function extractKeyFromMapCallback(callback) {
|
|
24295
|
-
const
|
|
24296
|
-
if (
|
|
24297
|
-
|
|
24442
|
+
const returnedKeyExpressions = getReturnedKeyExpressionsFromCallback(callback);
|
|
24443
|
+
if (returnedKeyExpressions.length === 1) {
|
|
24444
|
+
return returnedKeyExpressions[0];
|
|
24445
|
+
}
|
|
24446
|
+
if (returnedKeyExpressions.length > 1) {
|
|
24447
|
+
const [firstKey2, ...restKeys2] = returnedKeyExpressions;
|
|
24448
|
+
const firstSignature2 = keyExpressionSignature(firstKey2);
|
|
24449
|
+
if (firstSignature2 && restKeys2.every((keyExpr) => keyExpressionSignature(keyExpr) === firstSignature2)) {
|
|
24450
|
+
return firstKey2;
|
|
24451
|
+
}
|
|
24452
|
+
}
|
|
24453
|
+
const returned = getReturnedJSXFromCallback(callback);
|
|
24454
|
+
if (returned.length === 0) return void 0;
|
|
24455
|
+
const keyExpressions = returned.map((jsx) => extractKeyFromAttributes(jsx.attributes));
|
|
24456
|
+
if (keyExpressions.some((expr) => !expr)) return void 0;
|
|
24457
|
+
const [firstKey, ...restKeys] = keyExpressions;
|
|
24458
|
+
const firstSignature = keyExpressionSignature(firstKey);
|
|
24459
|
+
if (!firstSignature) return void 0;
|
|
24460
|
+
const allBranchesSameKey = restKeys.every(
|
|
24461
|
+
(keyExpr) => keyExpressionSignature(keyExpr) === firstSignature
|
|
24462
|
+
);
|
|
24463
|
+
if (!allBranchesSameKey) return void 0;
|
|
24464
|
+
return firstKey;
|
|
24298
24465
|
}
|
|
24299
24466
|
|
|
24300
24467
|
// src/ir/codegen-overrides.ts
|
|
@@ -24899,6 +25066,15 @@ function buildListCallExpression(expr, statements, ctx, ops) {
|
|
|
24899
25066
|
ctx.inListRender = true;
|
|
24900
25067
|
let callbackExpr = ops.lowerExpression(mapCallback, ctx);
|
|
24901
25068
|
ctx.inListRender = prevInListRender;
|
|
25069
|
+
const shouldDeferOptionalCallbackEvaluation = isOptional && !t4.isArrowFunctionExpression(callbackExpr) && !t4.isFunctionExpression(callbackExpr);
|
|
25070
|
+
let deferredCallbackId = null;
|
|
25071
|
+
let deferredCallbackInitId = null;
|
|
25072
|
+
let deferredItemsId = null;
|
|
25073
|
+
if (shouldDeferOptionalCallbackEvaluation) {
|
|
25074
|
+
deferredCallbackId = ops.genTemp(ctx, "mapCb");
|
|
25075
|
+
deferredCallbackInitId = ops.genTemp(ctx, "mapCbReady");
|
|
25076
|
+
deferredItemsId = ops.genTemp(ctx, "mapItems");
|
|
25077
|
+
}
|
|
24902
25078
|
const capturedKeyParamName = ctx.listKeyParamName;
|
|
24903
25079
|
ctx.listKeyExpr = prevListKeyExpr;
|
|
24904
25080
|
ctx.listItemParamName = prevListItemParamName;
|
|
@@ -24998,7 +25174,7 @@ function buildListCallExpression(expr, statements, ctx, ops) {
|
|
|
24998
25174
|
],
|
|
24999
25175
|
keyExprAst
|
|
25000
25176
|
);
|
|
25001
|
-
const hasIndexParam = (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
25177
|
+
const hasIndexParam = shouldDeferOptionalCallbackEvaluation || (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
25002
25178
|
if (canConstifyKey && (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr))) {
|
|
25003
25179
|
const newParams = [...callbackExpr.params];
|
|
25004
25180
|
while (newParams.length < 2) {
|
|
@@ -25018,25 +25194,131 @@ function buildListCallExpression(expr, statements, ctx, ops) {
|
|
|
25018
25194
|
}
|
|
25019
25195
|
}
|
|
25020
25196
|
statements.push(...hoistedStatements);
|
|
25197
|
+
if (shouldDeferOptionalCallbackEvaluation) {
|
|
25198
|
+
statements.push(
|
|
25199
|
+
t4.variableDeclaration("let", [
|
|
25200
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackId, true))
|
|
25201
|
+
]),
|
|
25202
|
+
t4.variableDeclaration("let", [
|
|
25203
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackInitId, true), t4.booleanLiteral(false))
|
|
25204
|
+
])
|
|
25205
|
+
);
|
|
25206
|
+
}
|
|
25207
|
+
const getItemsExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25208
|
+
[],
|
|
25209
|
+
t4.blockStatement([
|
|
25210
|
+
t4.variableDeclaration("const", [
|
|
25211
|
+
t4.variableDeclarator(
|
|
25212
|
+
t4.cloneNode(deferredItemsId, true),
|
|
25213
|
+
t4.cloneNode(arrayExprBase, true)
|
|
25214
|
+
)
|
|
25215
|
+
]),
|
|
25216
|
+
t4.ifStatement(
|
|
25217
|
+
t4.binaryExpression("==", t4.cloneNode(deferredItemsId, true), t4.nullLiteral()),
|
|
25218
|
+
t4.blockStatement([t4.returnStatement(t4.arrayExpression([]))])
|
|
25219
|
+
),
|
|
25220
|
+
t4.ifStatement(
|
|
25221
|
+
t4.unaryExpression("!", t4.cloneNode(deferredCallbackInitId, true)),
|
|
25222
|
+
t4.blockStatement([
|
|
25223
|
+
t4.expressionStatement(
|
|
25224
|
+
t4.assignmentExpression(
|
|
25225
|
+
"=",
|
|
25226
|
+
t4.cloneNode(deferredCallbackId, true),
|
|
25227
|
+
t4.cloneNode(callbackExpr, true)
|
|
25228
|
+
)
|
|
25229
|
+
),
|
|
25230
|
+
t4.expressionStatement(
|
|
25231
|
+
t4.assignmentExpression(
|
|
25232
|
+
"=",
|
|
25233
|
+
t4.cloneNode(deferredCallbackInitId, true),
|
|
25234
|
+
t4.booleanLiteral(true)
|
|
25235
|
+
)
|
|
25236
|
+
)
|
|
25237
|
+
])
|
|
25238
|
+
),
|
|
25239
|
+
t4.returnStatement(t4.cloneNode(deferredItemsId, true))
|
|
25240
|
+
])
|
|
25241
|
+
) : t4.arrowFunctionExpression([], arrayExpr);
|
|
25242
|
+
const renderExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25243
|
+
[t4.identifier("__item"), t4.identifier("__index"), t4.identifier("__key")],
|
|
25244
|
+
t4.callExpression(t4.cloneNode(deferredCallbackId, true), [
|
|
25245
|
+
t4.identifier("__item"),
|
|
25246
|
+
t4.identifier("__index"),
|
|
25247
|
+
t4.identifier("__key")
|
|
25248
|
+
])
|
|
25249
|
+
) : callbackExpr;
|
|
25021
25250
|
listCall = t4.callExpression(t4.identifier(RUNTIME_ALIASES.keyedList), [
|
|
25022
|
-
|
|
25251
|
+
getItemsExpr,
|
|
25023
25252
|
keyFn,
|
|
25024
|
-
|
|
25253
|
+
renderExpr,
|
|
25025
25254
|
t4.booleanLiteral(hasIndexParam)
|
|
25026
25255
|
]);
|
|
25027
25256
|
} else {
|
|
25028
25257
|
statements.push(...hoistedStatements);
|
|
25258
|
+
if (shouldDeferOptionalCallbackEvaluation) {
|
|
25259
|
+
statements.push(
|
|
25260
|
+
t4.variableDeclaration("let", [
|
|
25261
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackId, true))
|
|
25262
|
+
]),
|
|
25263
|
+
t4.variableDeclaration("let", [
|
|
25264
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackInitId, true), t4.booleanLiteral(false))
|
|
25265
|
+
])
|
|
25266
|
+
);
|
|
25267
|
+
}
|
|
25029
25268
|
const itemParamName = t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr) ? t4.isIdentifier(callbackExpr.params[0]) ? callbackExpr.params[0].name : "__item" : "__item";
|
|
25030
25269
|
const indexParamName = t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr) ? t4.isIdentifier(callbackExpr.params[1]) ? callbackExpr.params[1].name : "__index" : "__index";
|
|
25031
|
-
const hasIndexParam = (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
25270
|
+
const hasIndexParam = shouldDeferOptionalCallbackEvaluation || (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
25271
|
+
const getItemsExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25272
|
+
[],
|
|
25273
|
+
t4.blockStatement([
|
|
25274
|
+
t4.variableDeclaration("const", [
|
|
25275
|
+
t4.variableDeclarator(
|
|
25276
|
+
t4.cloneNode(deferredItemsId, true),
|
|
25277
|
+
t4.cloneNode(arrayExprBase, true)
|
|
25278
|
+
)
|
|
25279
|
+
]),
|
|
25280
|
+
t4.ifStatement(
|
|
25281
|
+
t4.binaryExpression("==", t4.cloneNode(deferredItemsId, true), t4.nullLiteral()),
|
|
25282
|
+
t4.blockStatement([t4.returnStatement(t4.arrayExpression([]))])
|
|
25283
|
+
),
|
|
25284
|
+
t4.ifStatement(
|
|
25285
|
+
t4.unaryExpression("!", t4.cloneNode(deferredCallbackInitId, true)),
|
|
25286
|
+
t4.blockStatement([
|
|
25287
|
+
t4.expressionStatement(
|
|
25288
|
+
t4.assignmentExpression(
|
|
25289
|
+
"=",
|
|
25290
|
+
t4.cloneNode(deferredCallbackId, true),
|
|
25291
|
+
t4.cloneNode(callbackExpr, true)
|
|
25292
|
+
)
|
|
25293
|
+
),
|
|
25294
|
+
t4.expressionStatement(
|
|
25295
|
+
t4.assignmentExpression(
|
|
25296
|
+
"=",
|
|
25297
|
+
t4.cloneNode(deferredCallbackInitId, true),
|
|
25298
|
+
t4.booleanLiteral(true)
|
|
25299
|
+
)
|
|
25300
|
+
)
|
|
25301
|
+
])
|
|
25302
|
+
),
|
|
25303
|
+
t4.returnStatement(t4.cloneNode(deferredItemsId, true))
|
|
25304
|
+
])
|
|
25305
|
+
) : t4.arrowFunctionExpression([], arrayExpr);
|
|
25306
|
+
const renderExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25307
|
+
[t4.identifier("__item"), t4.identifier("__index"), t4.identifier("__key")],
|
|
25308
|
+
t4.callExpression(t4.cloneNode(deferredCallbackId, true), [
|
|
25309
|
+
t4.identifier("__item"),
|
|
25310
|
+
t4.identifier("__index"),
|
|
25311
|
+
t4.identifier("__key")
|
|
25312
|
+
])
|
|
25313
|
+
) : callbackExpr;
|
|
25032
25314
|
const keyFn = t4.arrowFunctionExpression(
|
|
25033
25315
|
[t4.identifier(itemParamName), t4.identifier(indexParamName)],
|
|
25034
25316
|
t4.identifier(indexParamName)
|
|
25035
25317
|
);
|
|
25036
25318
|
listCall = t4.callExpression(t4.identifier(RUNTIME_ALIASES.keyedList), [
|
|
25037
|
-
|
|
25319
|
+
getItemsExpr,
|
|
25038
25320
|
keyFn,
|
|
25039
|
-
|
|
25321
|
+
renderExpr,
|
|
25040
25322
|
t4.booleanLiteral(hasIndexParam)
|
|
25041
25323
|
]);
|
|
25042
25324
|
}
|
|
@@ -25499,6 +25781,10 @@ function registerResumableComponent(componentName, ctx) {
|
|
|
25499
25781
|
const hostParam = t4.identifier("host");
|
|
25500
25782
|
const snapshotId = t4.identifier("snapshot");
|
|
25501
25783
|
const ctxId = t4.identifier("ctx");
|
|
25784
|
+
const runtimeModuleUrlExpr = t4.memberExpression(
|
|
25785
|
+
t4.metaProperty(t4.identifier("import"), t4.identifier("meta")),
|
|
25786
|
+
t4.identifier("url")
|
|
25787
|
+
);
|
|
25502
25788
|
ctx.helpersUsed.add("getSSRScope");
|
|
25503
25789
|
ctx.helpersUsed.add("ensureScope");
|
|
25504
25790
|
ctx.helpersUsed.add("prepareContext");
|
|
@@ -25572,7 +25858,10 @@ function registerResumableComponent(componentName, ctx) {
|
|
|
25572
25858
|
ctx.helpersUsed.add("registerResume");
|
|
25573
25859
|
const registerCall = t4.expressionStatement(
|
|
25574
25860
|
t4.callExpression(t4.identifier(RUNTIME_ALIASES.registerResume), [
|
|
25575
|
-
t4.
|
|
25861
|
+
t4.callExpression(t4.identifier(RUNTIME_ALIASES.qrl), [
|
|
25862
|
+
runtimeModuleUrlExpr,
|
|
25863
|
+
t4.stringLiteral(resumeExport)
|
|
25864
|
+
]),
|
|
25576
25865
|
resumeFnId
|
|
25577
25866
|
])
|
|
25578
25867
|
);
|
|
@@ -27362,18 +27651,8 @@ function lowerExpressionImpl(expr, ctx, valueUsed = true) {
|
|
|
27362
27651
|
blocks,
|
|
27363
27652
|
meta: { fromExpression: true }
|
|
27364
27653
|
};
|
|
27365
|
-
const cfg = analyzeCFG(fn.blocks);
|
|
27366
|
-
const hasLoop = cfg.loopHeaders.size > 0 || cfg.backEdges.size > 0;
|
|
27367
27654
|
const { node, diagnostics } = structurizeCFGWithDiagnostics(fn);
|
|
27368
|
-
const structured = node.kind === "stateMachine"
|
|
27369
|
-
kind: "stateMachine",
|
|
27370
|
-
blocks: fn.blocks.map((block) => ({
|
|
27371
|
-
blockId: block.id,
|
|
27372
|
-
instructions: block.instructions,
|
|
27373
|
-
terminator: block.terminator
|
|
27374
|
-
})),
|
|
27375
|
-
entryBlock: fn.blocks[0]?.id ?? 0
|
|
27376
|
-
} : diagnostics.isComplete ? node : {
|
|
27655
|
+
const structured = node.kind === "stateMachine" ? node : diagnostics.isComplete ? node : {
|
|
27377
27656
|
kind: "stateMachine",
|
|
27378
27657
|
blocks: fn.blocks.map((block) => ({
|
|
27379
27658
|
blockId: block.id,
|
|
@@ -33935,6 +34214,506 @@ function getRootIdentifier(expr, t4) {
|
|
|
33935
34214
|
return null;
|
|
33936
34215
|
}
|
|
33937
34216
|
|
|
34217
|
+
// src/tooling/analyze.ts
|
|
34218
|
+
var import_core2 = require("@babel/core");
|
|
34219
|
+
|
|
34220
|
+
// src/tooling/trace-infer.ts
|
|
34221
|
+
var TRACE_REGEX_ESCAPES = /[.*+?^${}()|[\]\\]/g;
|
|
34222
|
+
var IDENTIFIER_NAME = /^[A-Za-z_$][\w$]*$/;
|
|
34223
|
+
function isIdentifierName(name) {
|
|
34224
|
+
return IDENTIFIER_NAME.test(name);
|
|
34225
|
+
}
|
|
34226
|
+
function lineContainsIdentifier(lineText, identifier2) {
|
|
34227
|
+
const pattern = new RegExp(`\\b${identifier2.replace(TRACE_REGEX_ESCAPES, "\\$&")}\\b`);
|
|
34228
|
+
return pattern.test(lineText);
|
|
34229
|
+
}
|
|
34230
|
+
function lineContainsAnyIdentifier(lineText, identifiers) {
|
|
34231
|
+
for (const id of identifiers) {
|
|
34232
|
+
if (lineContainsIdentifier(lineText, id)) return true;
|
|
34233
|
+
}
|
|
34234
|
+
return false;
|
|
34235
|
+
}
|
|
34236
|
+
function pushTraceMarker(markersByLine, line, marker) {
|
|
34237
|
+
const markers = markersByLine.get(line);
|
|
34238
|
+
if (!markers) {
|
|
34239
|
+
markersByLine.set(line, [marker]);
|
|
34240
|
+
return;
|
|
34241
|
+
}
|
|
34242
|
+
const duplicate = markers.some(
|
|
34243
|
+
(existing) => existing.kind === marker.kind && existing.label === marker.label
|
|
34244
|
+
);
|
|
34245
|
+
if (!duplicate) markers.push(marker);
|
|
34246
|
+
}
|
|
34247
|
+
function inferReactiveLocalNames(startLine, endLine, sourceLines, baseReactiveNames) {
|
|
34248
|
+
const reactiveNames = new Set(baseReactiveNames);
|
|
34249
|
+
const declarationLines = [];
|
|
34250
|
+
const declarationPattern = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(.+?)(?:;)?$/;
|
|
34251
|
+
for (let line = startLine; line <= endLine; line++) {
|
|
34252
|
+
const text = (sourceLines[line - 1] ?? "").trim();
|
|
34253
|
+
if (!text) continue;
|
|
34254
|
+
const withoutComment = text.replace(/\/\/.*$/, "").trim();
|
|
34255
|
+
if (!withoutComment) continue;
|
|
34256
|
+
const match = withoutComment.match(declarationPattern);
|
|
34257
|
+
if (!match) continue;
|
|
34258
|
+
const name = match[1];
|
|
34259
|
+
const expression = match[2];
|
|
34260
|
+
if (!name || !expression) continue;
|
|
34261
|
+
declarationLines.push({ name, expression });
|
|
34262
|
+
}
|
|
34263
|
+
let changed = true;
|
|
34264
|
+
while (changed) {
|
|
34265
|
+
changed = false;
|
|
34266
|
+
for (const declaration of declarationLines) {
|
|
34267
|
+
if (reactiveNames.has(declaration.name)) continue;
|
|
34268
|
+
if (!lineContainsAnyIdentifier(declaration.expression, reactiveNames)) continue;
|
|
34269
|
+
reactiveNames.add(declaration.name);
|
|
34270
|
+
changed = true;
|
|
34271
|
+
}
|
|
34272
|
+
}
|
|
34273
|
+
return reactiveNames;
|
|
34274
|
+
}
|
|
34275
|
+
function isStateCallInstruction(instr) {
|
|
34276
|
+
if (instr.kind !== "Assign") return false;
|
|
34277
|
+
const value = instr.value;
|
|
34278
|
+
return value.kind === "CallExpression" && value.callee.kind === "Identifier" && value.callee.name === "$state";
|
|
34279
|
+
}
|
|
34280
|
+
function collectStateDeclNames(fn) {
|
|
34281
|
+
const result = [];
|
|
34282
|
+
for (const block of fn.blocks) {
|
|
34283
|
+
for (const instr of block.instructions) {
|
|
34284
|
+
if (!isStateCallInstruction(instr) || !instr.loc) continue;
|
|
34285
|
+
const name = deSSAVarName(instr.target.name);
|
|
34286
|
+
if (!isIdentifierName(name)) continue;
|
|
34287
|
+
result.push({ name, line: instr.loc.start.line });
|
|
34288
|
+
}
|
|
34289
|
+
}
|
|
34290
|
+
return result;
|
|
34291
|
+
}
|
|
34292
|
+
function expressionContainsEffectCall(instr) {
|
|
34293
|
+
const value = instr.kind === "Assign" || instr.kind === "Expression" ? instr.value : null;
|
|
34294
|
+
if (!value || !instr.loc) return null;
|
|
34295
|
+
let found = false;
|
|
34296
|
+
walkExpression(value, (expr) => {
|
|
34297
|
+
if (expr.kind === "CallExpression" && expr.callee.kind === "Identifier" && deSSAVarName(expr.callee.name) === "$effect") {
|
|
34298
|
+
found = true;
|
|
34299
|
+
}
|
|
34300
|
+
});
|
|
34301
|
+
return found ? instr.loc.start.line : null;
|
|
34302
|
+
}
|
|
34303
|
+
function flattenRegions2(regions) {
|
|
34304
|
+
if (!regions || regions.length === 0) return [];
|
|
34305
|
+
const result = [];
|
|
34306
|
+
const visit = (region) => {
|
|
34307
|
+
result.push(region);
|
|
34308
|
+
region.children?.forEach((child) => visit(child));
|
|
34309
|
+
};
|
|
34310
|
+
regions.forEach((region) => visit(region));
|
|
34311
|
+
return result;
|
|
34312
|
+
}
|
|
34313
|
+
function findContainingRegion2(line, flatRegions) {
|
|
34314
|
+
let best;
|
|
34315
|
+
for (const region of flatRegions) {
|
|
34316
|
+
if (region.startLine === void 0 || region.endLine === void 0 || line < region.startLine || line > region.endLine) {
|
|
34317
|
+
continue;
|
|
34318
|
+
}
|
|
34319
|
+
const bestSpan = best && best.startLine !== void 0 && best.endLine !== void 0 ? best.endLine - best.startLine : Number.POSITIVE_INFINITY;
|
|
34320
|
+
const span = region.endLine - region.startLine;
|
|
34321
|
+
if (span <= bestSpan) best = region;
|
|
34322
|
+
}
|
|
34323
|
+
return best;
|
|
34324
|
+
}
|
|
34325
|
+
function inferTraceMarkersForComponent(input) {
|
|
34326
|
+
const { fn, sourceLines, startLine, endLine, verbosity, regions } = input;
|
|
34327
|
+
const markersByLine = /* @__PURE__ */ new Map();
|
|
34328
|
+
pushTraceMarker(markersByLine, startLine, {
|
|
34329
|
+
kind: "once",
|
|
34330
|
+
label: "Component setup runs on mount"
|
|
34331
|
+
});
|
|
34332
|
+
const stateDecls = collectStateDeclNames(fn);
|
|
34333
|
+
const reactiveNames = inferReactiveLocalNames(
|
|
34334
|
+
startLine,
|
|
34335
|
+
endLine,
|
|
34336
|
+
sourceLines,
|
|
34337
|
+
stateDecls.map((item) => item.name)
|
|
34338
|
+
);
|
|
34339
|
+
for (const stateDecl of stateDecls) {
|
|
34340
|
+
pushTraceMarker(markersByLine, stateDecl.line, {
|
|
34341
|
+
kind: "once",
|
|
34342
|
+
label: "Signal initialization runs once"
|
|
34343
|
+
});
|
|
34344
|
+
}
|
|
34345
|
+
for (const block of fn.blocks) {
|
|
34346
|
+
for (const instr of block.instructions) {
|
|
34347
|
+
const line = expressionContainsEffectCall(instr);
|
|
34348
|
+
if (!line || line < startLine || line > endLine) continue;
|
|
34349
|
+
pushTraceMarker(markersByLine, line, {
|
|
34350
|
+
kind: "effect",
|
|
34351
|
+
label: "Effect reruns when dependencies change"
|
|
34352
|
+
});
|
|
34353
|
+
}
|
|
34354
|
+
}
|
|
34355
|
+
const flatRegions = flattenRegions2(regions);
|
|
34356
|
+
for (let line = startLine; line <= endLine; line++) {
|
|
34357
|
+
const lineText = sourceLines[line - 1] ?? "";
|
|
34358
|
+
if (!lineText) continue;
|
|
34359
|
+
const hasReactiveName = lineContainsAnyIdentifier(lineText, reactiveNames);
|
|
34360
|
+
if (hasReactiveName && /\{[^}]*\b[A-Za-z_$][\w$]*\b[^}]*\}/.test(lineText)) {
|
|
34361
|
+
pushTraceMarker(markersByLine, line, {
|
|
34362
|
+
kind: "reactive",
|
|
34363
|
+
label: "JSX expression updates with reactive values"
|
|
34364
|
+
});
|
|
34365
|
+
}
|
|
34366
|
+
if (hasReactiveName && /\bconsole\.(?:log|debug|info|warn|error)\s*\(/.test(lineText)) {
|
|
34367
|
+
pushTraceMarker(markersByLine, line, {
|
|
34368
|
+
kind: "reactive",
|
|
34369
|
+
label: "Statement reruns when reactive values change"
|
|
34370
|
+
});
|
|
34371
|
+
}
|
|
34372
|
+
if (/\b(?:\$effect|effect)\s*\(/.test(lineText)) {
|
|
34373
|
+
pushTraceMarker(markersByLine, line, {
|
|
34374
|
+
kind: "effect",
|
|
34375
|
+
label: "Effect callback executes reactively"
|
|
34376
|
+
});
|
|
34377
|
+
}
|
|
34378
|
+
if (verbosity === "verbose" && !hasReactiveName && /\{[^}]*\}/.test(lineText)) {
|
|
34379
|
+
pushTraceMarker(markersByLine, line, {
|
|
34380
|
+
kind: "once",
|
|
34381
|
+
label: "JSX expression runs during setup only"
|
|
34382
|
+
});
|
|
34383
|
+
}
|
|
34384
|
+
if (/\bconsole\.(?:log|debug|info|warn|error)\s*\(/.test(lineText) && !hasReactiveName && line !== startLine) {
|
|
34385
|
+
pushTraceMarker(markersByLine, line, {
|
|
34386
|
+
kind: "once",
|
|
34387
|
+
label: "Statement runs only during setup"
|
|
34388
|
+
});
|
|
34389
|
+
}
|
|
34390
|
+
const containingRegion = findContainingRegion2(line, flatRegions);
|
|
34391
|
+
if (!containingRegion) continue;
|
|
34392
|
+
const markers = markersByLine.get(line);
|
|
34393
|
+
if (!markers) continue;
|
|
34394
|
+
for (const marker of markers) {
|
|
34395
|
+
marker.regionId = containingRegion.id;
|
|
34396
|
+
marker.deps = containingRegion.dependencies;
|
|
34397
|
+
}
|
|
34398
|
+
}
|
|
34399
|
+
return [...markersByLine.entries()].sort((a, b) => a[0] - b[0]).map(([line, markers]) => ({ line, markers }));
|
|
34400
|
+
}
|
|
34401
|
+
|
|
34402
|
+
// src/tooling/analyze.ts
|
|
34403
|
+
function mergeLoc(a, b) {
|
|
34404
|
+
if (!a) return b ?? null;
|
|
34405
|
+
if (!b) return a;
|
|
34406
|
+
const start = b.start.line < a.start.line || b.start.line === a.start.line && b.start.column < a.start.column ? b.start : a.start;
|
|
34407
|
+
const end = b.end.line > a.end.line || b.end.line === a.end.line && b.end.column > a.end.column ? b.end : a.end;
|
|
34408
|
+
return {
|
|
34409
|
+
start,
|
|
34410
|
+
end,
|
|
34411
|
+
filename: a.filename ?? b.filename,
|
|
34412
|
+
identifierName: a.identifierName ?? b.identifierName
|
|
34413
|
+
};
|
|
34414
|
+
}
|
|
34415
|
+
function expressionContainsMacroCall(expr, macroName) {
|
|
34416
|
+
let found = false;
|
|
34417
|
+
const visit = (value) => {
|
|
34418
|
+
if (found) return;
|
|
34419
|
+
if (value.kind === "CallExpression" && value.callee.kind === "Identifier" && deSSAVarName(value.callee.name) === macroName) {
|
|
34420
|
+
found = true;
|
|
34421
|
+
return;
|
|
34422
|
+
}
|
|
34423
|
+
switch (value.kind) {
|
|
34424
|
+
case "CallExpression":
|
|
34425
|
+
case "OptionalCallExpression":
|
|
34426
|
+
visit(value.callee);
|
|
34427
|
+
value.arguments.forEach((arg) => visit(arg));
|
|
34428
|
+
return;
|
|
34429
|
+
case "MemberExpression":
|
|
34430
|
+
case "OptionalMemberExpression":
|
|
34431
|
+
visit(value.object);
|
|
34432
|
+
if (value.computed) visit(value.property);
|
|
34433
|
+
return;
|
|
34434
|
+
case "BinaryExpression":
|
|
34435
|
+
case "LogicalExpression":
|
|
34436
|
+
visit(value.left);
|
|
34437
|
+
visit(value.right);
|
|
34438
|
+
return;
|
|
34439
|
+
case "UnaryExpression":
|
|
34440
|
+
case "AwaitExpression":
|
|
34441
|
+
case "UpdateExpression":
|
|
34442
|
+
case "SpreadElement":
|
|
34443
|
+
visit(value.argument);
|
|
34444
|
+
return;
|
|
34445
|
+
case "ConditionalExpression":
|
|
34446
|
+
visit(value.test);
|
|
34447
|
+
visit(value.consequent);
|
|
34448
|
+
visit(value.alternate);
|
|
34449
|
+
return;
|
|
34450
|
+
case "ArrayExpression":
|
|
34451
|
+
value.elements.forEach((el) => visit(el));
|
|
34452
|
+
return;
|
|
34453
|
+
case "ObjectExpression":
|
|
34454
|
+
value.properties.forEach((prop) => {
|
|
34455
|
+
if (prop.kind === "SpreadElement") {
|
|
34456
|
+
visit(prop.argument);
|
|
34457
|
+
return;
|
|
34458
|
+
}
|
|
34459
|
+
if (prop.computed) visit(prop.key);
|
|
34460
|
+
visit(prop.value);
|
|
34461
|
+
});
|
|
34462
|
+
return;
|
|
34463
|
+
case "TemplateLiteral":
|
|
34464
|
+
value.expressions.forEach((item) => visit(item));
|
|
34465
|
+
return;
|
|
34466
|
+
case "AssignmentExpression":
|
|
34467
|
+
visit(value.left);
|
|
34468
|
+
visit(value.right);
|
|
34469
|
+
return;
|
|
34470
|
+
case "SequenceExpression":
|
|
34471
|
+
value.expressions.forEach((item) => visit(item));
|
|
34472
|
+
return;
|
|
34473
|
+
case "YieldExpression":
|
|
34474
|
+
if (value.argument) visit(value.argument);
|
|
34475
|
+
return;
|
|
34476
|
+
case "TaggedTemplateExpression":
|
|
34477
|
+
visit(value.tag);
|
|
34478
|
+
value.quasi.expressions.forEach((item) => visit(item));
|
|
34479
|
+
return;
|
|
34480
|
+
case "ImportExpression":
|
|
34481
|
+
visit(value.source);
|
|
34482
|
+
return;
|
|
34483
|
+
case "ArrowFunction":
|
|
34484
|
+
if (Array.isArray(value.body)) {
|
|
34485
|
+
value.body.forEach((block) => {
|
|
34486
|
+
block.instructions.forEach((instr) => {
|
|
34487
|
+
if (instr.kind === "Assign" || instr.kind === "Expression") {
|
|
34488
|
+
visit(instr.value);
|
|
34489
|
+
}
|
|
34490
|
+
});
|
|
34491
|
+
});
|
|
34492
|
+
} else {
|
|
34493
|
+
visit(value.body);
|
|
34494
|
+
}
|
|
34495
|
+
return;
|
|
34496
|
+
case "FunctionExpression":
|
|
34497
|
+
value.body.forEach((block) => {
|
|
34498
|
+
block.instructions.forEach((instr) => {
|
|
34499
|
+
if (instr.kind === "Assign" || instr.kind === "Expression") {
|
|
34500
|
+
visit(instr.value);
|
|
34501
|
+
}
|
|
34502
|
+
});
|
|
34503
|
+
});
|
|
34504
|
+
return;
|
|
34505
|
+
case "JSXElement":
|
|
34506
|
+
if (typeof value.tagName !== "string") visit(value.tagName);
|
|
34507
|
+
value.attributes.forEach((attr) => {
|
|
34508
|
+
if (attr.isSpread && attr.spreadExpr) {
|
|
34509
|
+
visit(attr.spreadExpr);
|
|
34510
|
+
} else if (attr.value) {
|
|
34511
|
+
visit(attr.value);
|
|
34512
|
+
}
|
|
34513
|
+
});
|
|
34514
|
+
value.children.forEach((child) => {
|
|
34515
|
+
if (child.kind === "expression") visit(child.value);
|
|
34516
|
+
if (child.kind === "element") visit(child.value);
|
|
34517
|
+
});
|
|
34518
|
+
return;
|
|
34519
|
+
case "Identifier":
|
|
34520
|
+
case "Literal":
|
|
34521
|
+
case "MetaProperty":
|
|
34522
|
+
case "NewExpression":
|
|
34523
|
+
case "ClassExpression":
|
|
34524
|
+
case "ThisExpression":
|
|
34525
|
+
case "SuperExpression":
|
|
34526
|
+
if (value.kind === "NewExpression") {
|
|
34527
|
+
visit(value.callee);
|
|
34528
|
+
value.arguments.forEach((arg) => visit(arg));
|
|
34529
|
+
}
|
|
34530
|
+
if (value.kind === "ClassExpression" && value.superClass) visit(value.superClass);
|
|
34531
|
+
return;
|
|
34532
|
+
default:
|
|
34533
|
+
return;
|
|
34534
|
+
}
|
|
34535
|
+
};
|
|
34536
|
+
visit(expr);
|
|
34537
|
+
return found;
|
|
34538
|
+
}
|
|
34539
|
+
function instructionContainsMacroCall(instruction, macroName) {
|
|
34540
|
+
if (instruction.kind !== "Assign" && instruction.kind !== "Expression") return false;
|
|
34541
|
+
return expressionContainsMacroCall(instruction.value, macroName);
|
|
34542
|
+
}
|
|
34543
|
+
function functionUsesMacro(fn, macroName) {
|
|
34544
|
+
for (const block of fn.blocks) {
|
|
34545
|
+
for (const instruction of block.instructions) {
|
|
34546
|
+
if (instructionContainsMacroCall(instruction, macroName)) return true;
|
|
34547
|
+
}
|
|
34548
|
+
const term = block.terminator;
|
|
34549
|
+
if ("argument" in term && term.argument && expressionContainsMacroCall(term.argument, macroName)) {
|
|
34550
|
+
return true;
|
|
34551
|
+
}
|
|
34552
|
+
if (term.kind === "Branch" && expressionContainsMacroCall(term.test, macroName)) {
|
|
34553
|
+
return true;
|
|
34554
|
+
}
|
|
34555
|
+
if (term.kind === "Switch") {
|
|
34556
|
+
if (expressionContainsMacroCall(term.discriminant, macroName)) return true;
|
|
34557
|
+
if (term.cases.some((entry) => entry.test && expressionContainsMacroCall(entry.test, macroName))) {
|
|
34558
|
+
return true;
|
|
34559
|
+
}
|
|
34560
|
+
}
|
|
34561
|
+
}
|
|
34562
|
+
return false;
|
|
34563
|
+
}
|
|
34564
|
+
function computeRegionLoc(region, fn) {
|
|
34565
|
+
let loc = null;
|
|
34566
|
+
for (const instruction of region.instructions) {
|
|
34567
|
+
loc = mergeLoc(loc, instruction.loc);
|
|
34568
|
+
}
|
|
34569
|
+
for (const blockId of region.blocks) {
|
|
34570
|
+
const block = fn.blocks.find((entry) => entry.id === blockId);
|
|
34571
|
+
if (!block) continue;
|
|
34572
|
+
loc = mergeLoc(loc, block.terminator.loc);
|
|
34573
|
+
}
|
|
34574
|
+
return loc;
|
|
34575
|
+
}
|
|
34576
|
+
function regionToSerializable(region, fn) {
|
|
34577
|
+
const loc = computeRegionLoc(region, fn);
|
|
34578
|
+
return {
|
|
34579
|
+
id: region.id,
|
|
34580
|
+
startLine: loc?.start.line,
|
|
34581
|
+
startColumn: loc?.start.column,
|
|
34582
|
+
endLine: loc?.end.line,
|
|
34583
|
+
endColumn: loc?.end.column,
|
|
34584
|
+
dependencies: [...region.dependencies].map(deSSAVarName),
|
|
34585
|
+
declarations: [...region.declarations].map(deSSAVarName),
|
|
34586
|
+
hasControlFlow: region.hasControlFlow,
|
|
34587
|
+
hasReactiveWrites: region.declarations.size > 0,
|
|
34588
|
+
children: region.children.map((child) => regionToSerializable(child, fn))
|
|
34589
|
+
};
|
|
34590
|
+
}
|
|
34591
|
+
function warningSeverity(code) {
|
|
34592
|
+
const diagnosticCodes = new Set(getAllDiagnosticCodes());
|
|
34593
|
+
if (!diagnosticCodes.has(code)) return "warning" /* Warning */;
|
|
34594
|
+
return getDiagnosticInfo(code).severity;
|
|
34595
|
+
}
|
|
34596
|
+
function normalizeWarningToDiagnostic(warning) {
|
|
34597
|
+
return {
|
|
34598
|
+
code: warning.code,
|
|
34599
|
+
message: warning.message,
|
|
34600
|
+
severity: warningSeverity(warning.code),
|
|
34601
|
+
line: warning.line,
|
|
34602
|
+
column: warning.column
|
|
34603
|
+
};
|
|
34604
|
+
}
|
|
34605
|
+
function normalizeThrownError(error) {
|
|
34606
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
34607
|
+
return {
|
|
34608
|
+
code: "FICT-COMPILE",
|
|
34609
|
+
message,
|
|
34610
|
+
severity: "error" /* Error */,
|
|
34611
|
+
line: 0,
|
|
34612
|
+
column: 0
|
|
34613
|
+
};
|
|
34614
|
+
}
|
|
34615
|
+
function analyzeDiagnostics(code, fileName, options) {
|
|
34616
|
+
const warnings = [];
|
|
34617
|
+
const pluginOptions = {
|
|
34618
|
+
dev: true,
|
|
34619
|
+
filename: fileName,
|
|
34620
|
+
emitModuleMetadata: false,
|
|
34621
|
+
strictGuarantee: false,
|
|
34622
|
+
warningLevels: {
|
|
34623
|
+
...options.compilerOptions?.warningLevels ?? {},
|
|
34624
|
+
"FICT-R004": "warn"
|
|
34625
|
+
},
|
|
34626
|
+
...options.compilerOptions,
|
|
34627
|
+
onWarn: (warning) => warnings.push(warning)
|
|
34628
|
+
};
|
|
34629
|
+
try {
|
|
34630
|
+
(0, import_core2.transformSync)(code, {
|
|
34631
|
+
filename: fileName,
|
|
34632
|
+
configFile: false,
|
|
34633
|
+
babelrc: false,
|
|
34634
|
+
sourceType: "module",
|
|
34635
|
+
parserOpts: {
|
|
34636
|
+
sourceType: "module",
|
|
34637
|
+
plugins: ["typescript", "jsx"],
|
|
34638
|
+
allowReturnOutsideFunction: true
|
|
34639
|
+
},
|
|
34640
|
+
plugins: [[index_default, pluginOptions]],
|
|
34641
|
+
generatorOpts: {
|
|
34642
|
+
compact: false
|
|
34643
|
+
}
|
|
34644
|
+
});
|
|
34645
|
+
} catch (error) {
|
|
34646
|
+
return [...warnings.map(normalizeWarningToDiagnostic), normalizeThrownError(error)];
|
|
34647
|
+
}
|
|
34648
|
+
return warnings.map(normalizeWarningToDiagnostic);
|
|
34649
|
+
}
|
|
34650
|
+
function shouldIncludeFunction(fn) {
|
|
34651
|
+
return functionContainsJSX(fn) || functionUsesMacro(fn, "$state") || functionUsesMacro(fn, "$effect");
|
|
34652
|
+
}
|
|
34653
|
+
function parseFileAst(code, fileName) {
|
|
34654
|
+
const ast = (0, import_core2.parseSync)(code, {
|
|
34655
|
+
filename: fileName,
|
|
34656
|
+
sourceType: "module",
|
|
34657
|
+
parserOpts: {
|
|
34658
|
+
sourceType: "module",
|
|
34659
|
+
plugins: ["typescript", "jsx"],
|
|
34660
|
+
allowReturnOutsideFunction: true
|
|
34661
|
+
}
|
|
34662
|
+
});
|
|
34663
|
+
if (!ast || ast.type !== "File") {
|
|
34664
|
+
throw new Error("Failed to parse source file for Fict analysis.");
|
|
34665
|
+
}
|
|
34666
|
+
return ast;
|
|
34667
|
+
}
|
|
34668
|
+
function analyzeFictFile(code, fileName, options = {}) {
|
|
34669
|
+
const includeRegions = options.includeRegions ?? true;
|
|
34670
|
+
const includeDiagnostics = options.includeDiagnostics ?? true;
|
|
34671
|
+
const verbosity = options.verbosity ?? "minimal";
|
|
34672
|
+
const ast = parseFileAst(code, fileName);
|
|
34673
|
+
const hir = buildHIR(
|
|
34674
|
+
ast,
|
|
34675
|
+
{
|
|
34676
|
+
state: /* @__PURE__ */ new Set(["$state"]),
|
|
34677
|
+
effect: /* @__PURE__ */ new Set(["$effect"])
|
|
34678
|
+
},
|
|
34679
|
+
{
|
|
34680
|
+
dev: true,
|
|
34681
|
+
fileName
|
|
34682
|
+
}
|
|
34683
|
+
);
|
|
34684
|
+
const sourceLines = code.split(/\r?\n/);
|
|
34685
|
+
const components = [];
|
|
34686
|
+
for (const fn of hir.functions) {
|
|
34687
|
+
if (!fn.loc || !shouldIncludeFunction(fn)) continue;
|
|
34688
|
+
const startLine = fn.loc.start.line;
|
|
34689
|
+
const endLine = fn.loc.end.line;
|
|
34690
|
+
const scopeResult = analyzeReactiveScopesWithSSA(fn);
|
|
34691
|
+
const regionResult = generateRegions(fn, scopeResult);
|
|
34692
|
+
const regions = includeRegions ? regionResult.topLevelRegions.map((region) => regionToSerializable(region, fn)) : void 0;
|
|
34693
|
+
const trace = inferTraceMarkersForComponent({
|
|
34694
|
+
fn,
|
|
34695
|
+
sourceLines,
|
|
34696
|
+
startLine,
|
|
34697
|
+
endLine,
|
|
34698
|
+
verbosity,
|
|
34699
|
+
regions
|
|
34700
|
+
});
|
|
34701
|
+
components.push({
|
|
34702
|
+
name: fn.name ?? "<anonymous>",
|
|
34703
|
+
startLine,
|
|
34704
|
+
endLine,
|
|
34705
|
+
trace,
|
|
34706
|
+
regions
|
|
34707
|
+
});
|
|
34708
|
+
}
|
|
34709
|
+
const diagnostics = includeDiagnostics ? analyzeDiagnostics(code, fileName, options) : [];
|
|
34710
|
+
return {
|
|
34711
|
+
fileName,
|
|
34712
|
+
components,
|
|
34713
|
+
diagnostics
|
|
34714
|
+
};
|
|
34715
|
+
}
|
|
34716
|
+
|
|
33938
34717
|
// src/index.ts
|
|
33939
34718
|
function stripMacroImports(path2, t4) {
|
|
33940
34719
|
path2.traverse({
|
|
@@ -34828,46 +35607,77 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
34828
35607
|
path2.traverse({
|
|
34829
35608
|
JSXExpressionContainer(exprPath) {
|
|
34830
35609
|
const expr = exprPath.node.expression;
|
|
34831
|
-
if (!t4.isCallExpression(expr)) return;
|
|
34832
|
-
if (!t4.isMemberExpression(expr.callee) || !t4.isIdentifier(expr.callee.property, { name: "map" })) {
|
|
35610
|
+
if (!t4.isCallExpression(expr) && !t4.isOptionalCallExpression(expr)) return;
|
|
35611
|
+
if (!t4.isMemberExpression(expr.callee) && !t4.isOptionalMemberExpression(expr.callee) || !t4.isIdentifier(expr.callee.property, { name: "map" })) {
|
|
34833
35612
|
return;
|
|
34834
35613
|
}
|
|
34835
|
-
const
|
|
34836
|
-
if (!
|
|
34837
|
-
const
|
|
34838
|
-
|
|
34839
|
-
|
|
34840
|
-
const ret = fn.body.body.find((stmt) => t4.isReturnStatement(stmt));
|
|
34841
|
-
if (ret && t4.isReturnStatement(ret) && ret.argument && (t4.isJSXElement(ret.argument) || t4.isJSXFragment(ret.argument))) {
|
|
34842
|
-
return ret.argument;
|
|
34843
|
-
}
|
|
34844
|
-
}
|
|
34845
|
-
return null;
|
|
34846
|
-
};
|
|
34847
|
-
const jsx = getReturnedJsx(cb);
|
|
34848
|
-
if (!jsx) return;
|
|
34849
|
-
if (t4.isJSXFragment(jsx)) {
|
|
34850
|
-
warn({
|
|
34851
|
-
code: "FICT-J002",
|
|
34852
|
-
message: "Missing key prop in list rendering.",
|
|
34853
|
-
fileName,
|
|
34854
|
-
line: expr.loc?.start.line ?? 0,
|
|
34855
|
-
column: expr.loc ? expr.loc.start.column + 1 : 0
|
|
34856
|
-
});
|
|
35614
|
+
const callExprPath = exprPath.get("expression");
|
|
35615
|
+
if (!callExprPath.isCallExpression() && !callExprPath.isOptionalCallExpression()) return;
|
|
35616
|
+
const argPaths = callExprPath.get("arguments");
|
|
35617
|
+
const cbPath = Array.isArray(argPaths) ? argPaths[0] : void 0;
|
|
35618
|
+
if (!cbPath || !cbPath.isArrowFunctionExpression() && !cbPath.isFunctionExpression()) {
|
|
34857
35619
|
return;
|
|
34858
35620
|
}
|
|
34859
|
-
|
|
34860
|
-
|
|
34861
|
-
|
|
34862
|
-
|
|
34863
|
-
|
|
34864
|
-
|
|
35621
|
+
const getReturnedJsx = (fnPath) => {
|
|
35622
|
+
const collectReturnedJsxFromExpression = (node, returned2) => {
|
|
35623
|
+
if (!node) return;
|
|
35624
|
+
if (t4.isJSXElement(node) || t4.isJSXFragment(node)) {
|
|
35625
|
+
returned2.push(node);
|
|
35626
|
+
return;
|
|
35627
|
+
}
|
|
35628
|
+
if (t4.isConditionalExpression(node)) {
|
|
35629
|
+
collectReturnedJsxFromExpression(node.consequent, returned2);
|
|
35630
|
+
collectReturnedJsxFromExpression(node.alternate, returned2);
|
|
35631
|
+
return;
|
|
35632
|
+
}
|
|
35633
|
+
if (t4.isLogicalExpression(node)) {
|
|
35634
|
+
collectReturnedJsxFromExpression(node.left, returned2);
|
|
35635
|
+
collectReturnedJsxFromExpression(node.right, returned2);
|
|
35636
|
+
return;
|
|
35637
|
+
}
|
|
35638
|
+
if (t4.isSequenceExpression(node)) {
|
|
35639
|
+
const tail = node.expressions[node.expressions.length - 1];
|
|
35640
|
+
collectReturnedJsxFromExpression(tail, returned2);
|
|
35641
|
+
return;
|
|
35642
|
+
}
|
|
35643
|
+
if (t4.isParenthesizedExpression(node)) {
|
|
35644
|
+
collectReturnedJsxFromExpression(node.expression, returned2);
|
|
35645
|
+
return;
|
|
35646
|
+
}
|
|
35647
|
+
if (t4.isTSAsExpression(node) || t4.isTSTypeAssertion(node) || t4.isTSNonNullExpression(node) || t4.isTSSatisfiesExpression(node) || t4.isTypeCastExpression(node)) {
|
|
35648
|
+
collectReturnedJsxFromExpression(node.expression, returned2);
|
|
35649
|
+
}
|
|
35650
|
+
};
|
|
35651
|
+
const fn = fnPath.node;
|
|
35652
|
+
const returned = [];
|
|
35653
|
+
if (!t4.isBlockStatement(fn.body)) {
|
|
35654
|
+
collectReturnedJsxFromExpression(fn.body, returned);
|
|
35655
|
+
return returned;
|
|
34865
35656
|
}
|
|
34866
|
-
|
|
34867
|
-
|
|
35657
|
+
fnPath.get("body").traverse({
|
|
35658
|
+
Function(innerFnPath) {
|
|
35659
|
+
innerFnPath.skip();
|
|
35660
|
+
},
|
|
35661
|
+
ReturnStatement(retPath) {
|
|
35662
|
+
collectReturnedJsxFromExpression(retPath.node.argument, returned);
|
|
35663
|
+
}
|
|
35664
|
+
});
|
|
35665
|
+
return returned;
|
|
35666
|
+
};
|
|
35667
|
+
const returnedJsx = getReturnedJsx(cbPath);
|
|
35668
|
+
if (returnedJsx.length === 0) return;
|
|
35669
|
+
const hasMissingKeyBranch = returnedJsx.some((jsx) => {
|
|
35670
|
+
if (t4.isJSXFragment(jsx)) return true;
|
|
35671
|
+
let hasKey = false;
|
|
35672
|
+
for (const attr of jsx.openingElement.attributes) {
|
|
35673
|
+
if (t4.isJSXAttribute(attr) && t4.isJSXIdentifier(attr.name, { name: "key" })) {
|
|
35674
|
+
hasKey = true;
|
|
35675
|
+
break;
|
|
35676
|
+
}
|
|
34868
35677
|
}
|
|
34869
|
-
|
|
34870
|
-
|
|
35678
|
+
return !hasKey;
|
|
35679
|
+
});
|
|
35680
|
+
if (!hasMissingKeyBranch) return;
|
|
34871
35681
|
warn({
|
|
34872
35682
|
code: "FICT-J002",
|
|
34873
35683
|
message: "Missing key prop in list rendering.",
|
|
@@ -35430,8 +36240,10 @@ var createFictPlugin = (0, import_helper_plugin_utils.declare)(
|
|
|
35430
36240
|
var index_default = createFictPlugin;
|
|
35431
36241
|
// Annotate the CommonJS export names for ESM import in node:
|
|
35432
36242
|
0 && (module.exports = {
|
|
36243
|
+
analyzeFictFile,
|
|
35433
36244
|
clearModuleMetadata,
|
|
35434
36245
|
createFictPlugin,
|
|
36246
|
+
inferTraceMarkersForComponent,
|
|
35435
36247
|
resolveModuleMetadata,
|
|
35436
36248
|
setModuleMetadata
|
|
35437
36249
|
});
|