@fictjs/compiler 0.14.0 → 0.16.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/README.md +3 -0
- package/dist/index.cjs +1123 -211
- package/dist/index.d.cts +393 -1
- package/dist/index.d.ts +393 -1
- package/dist/index.js +1121 -211
- 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
|
});
|
|
@@ -14174,6 +14176,7 @@ var RUNTIME_HELPERS = {
|
|
|
14174
14176
|
bindEvent: "bindEvent",
|
|
14175
14177
|
callEventHandler: "callEventHandler",
|
|
14176
14178
|
bindRef: "bindRef",
|
|
14179
|
+
spread: "spread",
|
|
14177
14180
|
nonReactive: "nonReactive",
|
|
14178
14181
|
toNodeArray: "toNodeArray",
|
|
14179
14182
|
template: "template",
|
|
@@ -14231,6 +14234,7 @@ var RUNTIME_ALIASES = {
|
|
|
14231
14234
|
bindEvent: "bindEvent",
|
|
14232
14235
|
callEventHandler: "callEventHandler",
|
|
14233
14236
|
bindRef: "bindRef",
|
|
14237
|
+
spread: "spread",
|
|
14234
14238
|
nonReactive: "nonReactive",
|
|
14235
14239
|
toNodeArray: "toNodeArray",
|
|
14236
14240
|
template: "template",
|
|
@@ -17086,6 +17090,37 @@ function clearModuleMetadata(options) {
|
|
|
17086
17090
|
}
|
|
17087
17091
|
|
|
17088
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 || {});
|
|
17089
17124
|
var DiagnosticMessages = {
|
|
17090
17125
|
["FICT-P001" /* FICT_P001 */]: "Props destructuring falls back to non-reactive binding.",
|
|
17091
17126
|
["FICT-P002" /* FICT_P002 */]: "Array rest in props destructuring falls back to non-reactive binding.",
|
|
@@ -17173,6 +17208,16 @@ function reportDiagnostic(ctx, code, node, context) {
|
|
|
17173
17208
|
});
|
|
17174
17209
|
}
|
|
17175
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
|
+
}
|
|
17176
17221
|
|
|
17177
17222
|
// src/ir/ssa.ts
|
|
17178
17223
|
function enterSSA(program) {
|
|
@@ -22616,138 +22661,212 @@ function emitConditionalChild(startMarkerId, endMarkerId, expr, statements, ctx,
|
|
|
22616
22661
|
);
|
|
22617
22662
|
}
|
|
22618
22663
|
|
|
22619
|
-
// src/ir/
|
|
22620
|
-
function
|
|
22621
|
-
|
|
22622
|
-
|
|
22623
|
-
|
|
22624
|
-
|
|
22625
|
-
|
|
22626
|
-
|
|
22627
|
-
|
|
22628
|
-
|
|
22629
|
-
|
|
22630
|
-
|
|
22631
|
-
|
|
22632
|
-
|
|
22633
|
-
|
|
22634
|
-
|
|
22635
|
-
|
|
22636
|
-
|
|
22637
|
-
|
|
22664
|
+
// src/ir/walk-expression.ts
|
|
22665
|
+
function assertNever(value) {
|
|
22666
|
+
throw new Error(`Unhandled node in walkExpression: ${JSON.stringify(value)}`);
|
|
22667
|
+
}
|
|
22668
|
+
function walkTerminator(term, visitNode, inFunctionBody) {
|
|
22669
|
+
switch (term.kind) {
|
|
22670
|
+
case "Return":
|
|
22671
|
+
if (term.argument) visitNode(term.argument, null, inFunctionBody);
|
|
22672
|
+
return;
|
|
22673
|
+
case "Throw":
|
|
22674
|
+
visitNode(term.argument, null, inFunctionBody);
|
|
22675
|
+
return;
|
|
22676
|
+
case "Branch":
|
|
22677
|
+
visitNode(term.test, null, inFunctionBody);
|
|
22678
|
+
return;
|
|
22679
|
+
case "Switch":
|
|
22680
|
+
visitNode(term.discriminant, null, inFunctionBody);
|
|
22681
|
+
term.cases.forEach((c) => {
|
|
22682
|
+
if (c.test) visitNode(c.test, null, inFunctionBody);
|
|
22683
|
+
});
|
|
22684
|
+
return;
|
|
22685
|
+
case "ForOf":
|
|
22686
|
+
visitNode(term.iterable, null, inFunctionBody);
|
|
22687
|
+
return;
|
|
22688
|
+
case "ForIn":
|
|
22689
|
+
visitNode(term.object, null, inFunctionBody);
|
|
22690
|
+
return;
|
|
22691
|
+
case "Jump":
|
|
22692
|
+
case "Unreachable":
|
|
22693
|
+
case "Break":
|
|
22694
|
+
case "Continue":
|
|
22695
|
+
case "Try":
|
|
22696
|
+
return;
|
|
22697
|
+
default:
|
|
22698
|
+
assertNever(term);
|
|
22699
|
+
}
|
|
22700
|
+
}
|
|
22701
|
+
function walkInstruction(instr, visitNode, inFunctionBody) {
|
|
22702
|
+
switch (instr.kind) {
|
|
22703
|
+
case "Assign":
|
|
22704
|
+
case "Expression":
|
|
22705
|
+
visitNode(instr.value, null, inFunctionBody);
|
|
22706
|
+
return;
|
|
22707
|
+
case "Phi":
|
|
22708
|
+
instr.sources.forEach((source) => visitNode(source.id, null, inFunctionBody));
|
|
22709
|
+
return;
|
|
22710
|
+
default:
|
|
22711
|
+
assertNever(instr);
|
|
22638
22712
|
}
|
|
22639
|
-
return void 0;
|
|
22640
22713
|
}
|
|
22641
|
-
function
|
|
22714
|
+
function walkBlocks(blocks, visitNode, inFunctionBody) {
|
|
22642
22715
|
for (const block of blocks) {
|
|
22643
|
-
|
|
22644
|
-
|
|
22645
|
-
|
|
22646
|
-
|
|
22647
|
-
|
|
22648
|
-
|
|
22649
|
-
|
|
22650
|
-
|
|
22651
|
-
|
|
22716
|
+
block.instructions.forEach((instr) => walkInstruction(instr, visitNode, inFunctionBody));
|
|
22717
|
+
walkTerminator(block.terminator, visitNode, inFunctionBody);
|
|
22718
|
+
}
|
|
22719
|
+
}
|
|
22720
|
+
function walkExpression(expr, visit, options = {}) {
|
|
22721
|
+
const includeFunctionBodies = options.includeFunctionBodies ?? true;
|
|
22722
|
+
const visitNode = (node, parent, inFunctionBody) => {
|
|
22723
|
+
visit(node, { parent, inFunctionBody });
|
|
22724
|
+
switch (node.kind) {
|
|
22725
|
+
case "Identifier":
|
|
22726
|
+
case "Literal":
|
|
22727
|
+
case "MetaProperty":
|
|
22728
|
+
case "ThisExpression":
|
|
22729
|
+
case "SuperExpression":
|
|
22730
|
+
return;
|
|
22731
|
+
case "ImportExpression":
|
|
22732
|
+
visitNode(node.source, node, inFunctionBody);
|
|
22733
|
+
return;
|
|
22734
|
+
case "CallExpression":
|
|
22735
|
+
case "OptionalCallExpression":
|
|
22736
|
+
visitNode(node.callee, node, inFunctionBody);
|
|
22737
|
+
node.arguments.forEach((arg) => visitNode(arg, node, inFunctionBody));
|
|
22738
|
+
return;
|
|
22739
|
+
case "MemberExpression":
|
|
22740
|
+
case "OptionalMemberExpression":
|
|
22741
|
+
visitNode(node.object, node, inFunctionBody);
|
|
22742
|
+
if (node.computed) {
|
|
22743
|
+
visitNode(node.property, node, inFunctionBody);
|
|
22744
|
+
}
|
|
22745
|
+
return;
|
|
22746
|
+
case "BinaryExpression":
|
|
22747
|
+
case "LogicalExpression":
|
|
22748
|
+
visitNode(node.left, node, inFunctionBody);
|
|
22749
|
+
visitNode(node.right, node, inFunctionBody);
|
|
22750
|
+
return;
|
|
22751
|
+
case "UnaryExpression":
|
|
22752
|
+
case "AwaitExpression":
|
|
22753
|
+
visitNode(node.argument, node, inFunctionBody);
|
|
22754
|
+
return;
|
|
22755
|
+
case "ConditionalExpression":
|
|
22756
|
+
visitNode(node.test, node, inFunctionBody);
|
|
22757
|
+
visitNode(node.consequent, node, inFunctionBody);
|
|
22758
|
+
visitNode(node.alternate, node, inFunctionBody);
|
|
22759
|
+
return;
|
|
22760
|
+
case "ArrayExpression":
|
|
22761
|
+
node.elements.forEach((el) => visitNode(el, node, inFunctionBody));
|
|
22762
|
+
return;
|
|
22763
|
+
case "ObjectExpression":
|
|
22764
|
+
node.properties.forEach((prop) => {
|
|
22765
|
+
if (prop.kind === "SpreadElement") {
|
|
22766
|
+
visitNode(prop.argument, node, inFunctionBody);
|
|
22767
|
+
} else {
|
|
22768
|
+
if (prop.computed) {
|
|
22769
|
+
visitNode(prop.key, node, inFunctionBody);
|
|
22770
|
+
}
|
|
22771
|
+
visitNode(prop.value, node, inFunctionBody);
|
|
22652
22772
|
}
|
|
22653
|
-
|
|
22654
|
-
|
|
22655
|
-
|
|
22656
|
-
|
|
22657
|
-
|
|
22658
|
-
const term = block.terminator;
|
|
22659
|
-
switch (term.kind) {
|
|
22660
|
-
case "Return":
|
|
22661
|
-
if (term.argument) collectExpressionDependencies(term.argument, deps);
|
|
22662
|
-
break;
|
|
22663
|
-
case "Throw":
|
|
22664
|
-
collectExpressionDependencies(term.argument, deps);
|
|
22665
|
-
break;
|
|
22666
|
-
case "Branch":
|
|
22667
|
-
collectExpressionDependencies(term.test, deps);
|
|
22668
|
-
break;
|
|
22669
|
-
case "Switch":
|
|
22670
|
-
collectExpressionDependencies(term.discriminant, deps);
|
|
22671
|
-
for (const c of term.cases) {
|
|
22672
|
-
if (c.test) collectExpressionDependencies(c.test, deps);
|
|
22773
|
+
});
|
|
22774
|
+
return;
|
|
22775
|
+
case "JSXElement":
|
|
22776
|
+
if (typeof node.tagName !== "string") {
|
|
22777
|
+
visitNode(node.tagName, node, inFunctionBody);
|
|
22673
22778
|
}
|
|
22674
|
-
|
|
22675
|
-
|
|
22676
|
-
|
|
22677
|
-
|
|
22678
|
-
|
|
22679
|
-
|
|
22680
|
-
|
|
22779
|
+
node.attributes.forEach((attr) => {
|
|
22780
|
+
if (attr.isSpread && attr.spreadExpr) {
|
|
22781
|
+
visitNode(attr.spreadExpr, node, inFunctionBody);
|
|
22782
|
+
} else if (attr.value) {
|
|
22783
|
+
visitNode(attr.value, node, inFunctionBody);
|
|
22784
|
+
}
|
|
22785
|
+
});
|
|
22786
|
+
node.children.forEach((child) => {
|
|
22787
|
+
if (child.kind === "expression") {
|
|
22788
|
+
visitNode(child.value, node, inFunctionBody);
|
|
22789
|
+
} else if (child.kind === "element") {
|
|
22790
|
+
visitNode(child.value, node, inFunctionBody);
|
|
22791
|
+
}
|
|
22792
|
+
});
|
|
22793
|
+
return;
|
|
22794
|
+
case "ArrowFunction":
|
|
22795
|
+
if (!includeFunctionBodies) return;
|
|
22796
|
+
if (node.isExpression && !Array.isArray(node.body)) {
|
|
22797
|
+
visitNode(node.body, node, true);
|
|
22798
|
+
} else if (Array.isArray(node.body)) {
|
|
22799
|
+
walkBlocks(node.body, visitNode, true);
|
|
22800
|
+
}
|
|
22801
|
+
return;
|
|
22802
|
+
case "FunctionExpression":
|
|
22803
|
+
if (!includeFunctionBodies) return;
|
|
22804
|
+
walkBlocks(node.body, visitNode, true);
|
|
22805
|
+
return;
|
|
22806
|
+
case "AssignmentExpression":
|
|
22807
|
+
visitNode(node.left, node, inFunctionBody);
|
|
22808
|
+
visitNode(node.right, node, inFunctionBody);
|
|
22809
|
+
return;
|
|
22810
|
+
case "UpdateExpression":
|
|
22811
|
+
visitNode(node.argument, node, inFunctionBody);
|
|
22812
|
+
return;
|
|
22813
|
+
case "TemplateLiteral":
|
|
22814
|
+
node.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
|
|
22815
|
+
return;
|
|
22816
|
+
case "SpreadElement":
|
|
22817
|
+
visitNode(node.argument, node, inFunctionBody);
|
|
22818
|
+
return;
|
|
22819
|
+
case "NewExpression":
|
|
22820
|
+
visitNode(node.callee, node, inFunctionBody);
|
|
22821
|
+
node.arguments.forEach((arg) => visitNode(arg, node, inFunctionBody));
|
|
22822
|
+
return;
|
|
22823
|
+
case "SequenceExpression":
|
|
22824
|
+
node.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
|
|
22825
|
+
return;
|
|
22826
|
+
case "YieldExpression":
|
|
22827
|
+
if (node.argument) {
|
|
22828
|
+
visitNode(node.argument, node, inFunctionBody);
|
|
22829
|
+
}
|
|
22830
|
+
return;
|
|
22831
|
+
case "TaggedTemplateExpression":
|
|
22832
|
+
visitNode(node.tag, node, inFunctionBody);
|
|
22833
|
+
node.quasi.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
|
|
22834
|
+
return;
|
|
22835
|
+
case "ClassExpression":
|
|
22836
|
+
if (node.superClass) {
|
|
22837
|
+
visitNode(node.superClass, node, inFunctionBody);
|
|
22838
|
+
}
|
|
22839
|
+
return;
|
|
22681
22840
|
default:
|
|
22682
|
-
|
|
22841
|
+
assertNever(node);
|
|
22683
22842
|
}
|
|
22843
|
+
};
|
|
22844
|
+
visitNode(expr, null, false);
|
|
22845
|
+
}
|
|
22846
|
+
|
|
22847
|
+
// src/ir/codegen-expression-deps.ts
|
|
22848
|
+
function getMemberDependencyPath(expr) {
|
|
22849
|
+
if (expr.kind !== "MemberExpression" && expr.kind !== "OptionalMemberExpression") return void 0;
|
|
22850
|
+
const depPath = extractDependencyPath(expr);
|
|
22851
|
+
if (!depPath || depPath.segments.length === 0) return void 0;
|
|
22852
|
+
const base = deSSAVarName(depPath.base);
|
|
22853
|
+
if (depPath.segments.some((segment) => segment.computed)) {
|
|
22854
|
+
return base;
|
|
22684
22855
|
}
|
|
22856
|
+
const tail = depPath.segments.map((segment) => segment.property).join(".");
|
|
22857
|
+
return tail ? `${base}.${tail}` : void 0;
|
|
22685
22858
|
}
|
|
22686
22859
|
function collectExpressionDependencies(expr, deps) {
|
|
22687
|
-
|
|
22688
|
-
|
|
22689
|
-
|
|
22690
|
-
|
|
22691
|
-
if (expr.kind === "ArrowFunction") {
|
|
22692
|
-
if (expr.isExpression && !Array.isArray(expr.body)) {
|
|
22693
|
-
collectExpressionDependencies(expr.body, deps);
|
|
22694
|
-
} else if (Array.isArray(expr.body)) {
|
|
22695
|
-
collectBlockDependencies(expr.body, deps);
|
|
22860
|
+
walkExpression(expr, (node) => {
|
|
22861
|
+
if (node.kind === "Identifier") {
|
|
22862
|
+
deps.add(deSSAVarName(node.name));
|
|
22863
|
+
return;
|
|
22696
22864
|
}
|
|
22697
|
-
|
|
22698
|
-
|
|
22699
|
-
|
|
22700
|
-
collectBlockDependencies(expr.body, deps);
|
|
22701
|
-
return;
|
|
22702
|
-
}
|
|
22703
|
-
if (expr.kind === "MemberExpression") {
|
|
22704
|
-
const path2 = getMemberDependencyPath(expr);
|
|
22705
|
-
if (path2) deps.add(path2);
|
|
22706
|
-
collectExpressionDependencies(expr.object, deps);
|
|
22707
|
-
if (expr.computed && expr.property.kind !== "Literal") {
|
|
22708
|
-
collectExpressionDependencies(expr.property, deps);
|
|
22865
|
+
const path2 = getMemberDependencyPath(node);
|
|
22866
|
+
if (path2) {
|
|
22867
|
+
deps.add(path2);
|
|
22709
22868
|
}
|
|
22710
|
-
|
|
22711
|
-
}
|
|
22712
|
-
if (expr.kind === "CallExpression") {
|
|
22713
|
-
collectExpressionDependencies(expr.callee, deps);
|
|
22714
|
-
expr.arguments.forEach((a) => collectExpressionDependencies(a, deps));
|
|
22715
|
-
return;
|
|
22716
|
-
}
|
|
22717
|
-
if (expr.kind === "BinaryExpression" || expr.kind === "LogicalExpression") {
|
|
22718
|
-
collectExpressionDependencies(expr.left, deps);
|
|
22719
|
-
collectExpressionDependencies(expr.right, deps);
|
|
22720
|
-
return;
|
|
22721
|
-
}
|
|
22722
|
-
if (expr.kind === "ConditionalExpression") {
|
|
22723
|
-
collectExpressionDependencies(expr.test, deps);
|
|
22724
|
-
collectExpressionDependencies(expr.consequent, deps);
|
|
22725
|
-
collectExpressionDependencies(expr.alternate, deps);
|
|
22726
|
-
return;
|
|
22727
|
-
}
|
|
22728
|
-
if (expr.kind === "UnaryExpression") {
|
|
22729
|
-
collectExpressionDependencies(expr.argument, deps);
|
|
22730
|
-
return;
|
|
22731
|
-
}
|
|
22732
|
-
if (expr.kind === "ArrayExpression") {
|
|
22733
|
-
expr.elements.forEach((el) => collectExpressionDependencies(el, deps));
|
|
22734
|
-
return;
|
|
22735
|
-
}
|
|
22736
|
-
if (expr.kind === "ObjectExpression") {
|
|
22737
|
-
expr.properties.forEach((p) => {
|
|
22738
|
-
if (p.kind === "SpreadElement") {
|
|
22739
|
-
collectExpressionDependencies(p.argument, deps);
|
|
22740
|
-
} else {
|
|
22741
|
-
if (p.computed) collectExpressionDependencies(p.key, deps);
|
|
22742
|
-
collectExpressionDependencies(p.value, deps);
|
|
22743
|
-
}
|
|
22744
|
-
});
|
|
22745
|
-
return;
|
|
22746
|
-
}
|
|
22747
|
-
if (expr.kind === "TemplateLiteral") {
|
|
22748
|
-
expr.expressions.forEach((e) => collectExpressionDependencies(e, deps));
|
|
22749
|
-
return;
|
|
22750
|
-
}
|
|
22869
|
+
});
|
|
22751
22870
|
}
|
|
22752
22871
|
|
|
22753
22872
|
// src/ir/codegen-reactive-kind.ts
|
|
@@ -24191,34 +24310,138 @@ function extractKeyFromAttributes(attributes) {
|
|
|
24191
24310
|
}
|
|
24192
24311
|
return void 0;
|
|
24193
24312
|
}
|
|
24313
|
+
function collectReturnedJSXFromExpression(expression, returned) {
|
|
24314
|
+
if (expression.kind === "JSXElement") {
|
|
24315
|
+
returned.push(expression);
|
|
24316
|
+
return;
|
|
24317
|
+
}
|
|
24318
|
+
if (expression.kind === "ConditionalExpression") {
|
|
24319
|
+
collectReturnedJSXFromExpression(expression.consequent, returned);
|
|
24320
|
+
collectReturnedJSXFromExpression(expression.alternate, returned);
|
|
24321
|
+
return;
|
|
24322
|
+
}
|
|
24323
|
+
if (expression.kind === "LogicalExpression") {
|
|
24324
|
+
collectReturnedJSXFromExpression(expression.left, returned);
|
|
24325
|
+
collectReturnedJSXFromExpression(expression.right, returned);
|
|
24326
|
+
return;
|
|
24327
|
+
}
|
|
24328
|
+
if (expression.kind === "SequenceExpression") {
|
|
24329
|
+
const tail = expression.expressions[expression.expressions.length - 1];
|
|
24330
|
+
if (tail) collectReturnedJSXFromExpression(tail, returned);
|
|
24331
|
+
}
|
|
24332
|
+
}
|
|
24333
|
+
function extractKeyExpressionFromReturnedExpression(expression) {
|
|
24334
|
+
if (expression.kind === "JSXElement") {
|
|
24335
|
+
return extractKeyFromAttributes(expression.attributes);
|
|
24336
|
+
}
|
|
24337
|
+
if (expression.kind === "ConditionalExpression") {
|
|
24338
|
+
const consequentKey = extractKeyExpressionFromReturnedExpression(expression.consequent);
|
|
24339
|
+
const alternateKey = extractKeyExpressionFromReturnedExpression(expression.alternate);
|
|
24340
|
+
if (!consequentKey || !alternateKey) return void 0;
|
|
24341
|
+
return {
|
|
24342
|
+
kind: "ConditionalExpression",
|
|
24343
|
+
test: expression.test,
|
|
24344
|
+
consequent: consequentKey,
|
|
24345
|
+
alternate: alternateKey,
|
|
24346
|
+
loc: expression.loc
|
|
24347
|
+
};
|
|
24348
|
+
}
|
|
24349
|
+
if (expression.kind === "SequenceExpression") {
|
|
24350
|
+
const tail = expression.expressions[expression.expressions.length - 1];
|
|
24351
|
+
return tail ? extractKeyExpressionFromReturnedExpression(tail) : void 0;
|
|
24352
|
+
}
|
|
24353
|
+
return void 0;
|
|
24354
|
+
}
|
|
24355
|
+
function getReturnedKeyExpressionsFromCallback(callback) {
|
|
24356
|
+
const returned = [];
|
|
24357
|
+
if (callback.kind === "ArrowFunction") {
|
|
24358
|
+
if (callback.isExpression && !Array.isArray(callback.body)) {
|
|
24359
|
+
const keyExpr = extractKeyExpressionFromReturnedExpression(callback.body);
|
|
24360
|
+
if (keyExpr) returned.push(keyExpr);
|
|
24361
|
+
return returned;
|
|
24362
|
+
}
|
|
24363
|
+
if (Array.isArray(callback.body)) {
|
|
24364
|
+
for (const block of callback.body) {
|
|
24365
|
+
const term = block.terminator;
|
|
24366
|
+
if (term.kind !== "Return" || !term.argument) continue;
|
|
24367
|
+
const keyExpr = extractKeyExpressionFromReturnedExpression(term.argument);
|
|
24368
|
+
if (keyExpr) returned.push(keyExpr);
|
|
24369
|
+
}
|
|
24370
|
+
}
|
|
24371
|
+
return returned;
|
|
24372
|
+
}
|
|
24373
|
+
if (callback.kind === "FunctionExpression") {
|
|
24374
|
+
for (const block of callback.body ?? []) {
|
|
24375
|
+
const term = block.terminator;
|
|
24376
|
+
if (term.kind !== "Return" || !term.argument) continue;
|
|
24377
|
+
const keyExpr = extractKeyExpressionFromReturnedExpression(term.argument);
|
|
24378
|
+
if (keyExpr) returned.push(keyExpr);
|
|
24379
|
+
}
|
|
24380
|
+
}
|
|
24381
|
+
return returned;
|
|
24382
|
+
}
|
|
24194
24383
|
function getReturnedJSXFromCallback(callback) {
|
|
24384
|
+
const returned = [];
|
|
24195
24385
|
if (callback.kind === "ArrowFunction") {
|
|
24196
|
-
if (callback.isExpression && !Array.isArray(callback.body)
|
|
24197
|
-
|
|
24386
|
+
if (callback.isExpression && !Array.isArray(callback.body)) {
|
|
24387
|
+
collectReturnedJSXFromExpression(callback.body, returned);
|
|
24388
|
+
return returned;
|
|
24198
24389
|
}
|
|
24199
24390
|
if (Array.isArray(callback.body)) {
|
|
24200
24391
|
for (const block of callback.body) {
|
|
24201
24392
|
const term = block.terminator;
|
|
24202
|
-
if (term.kind === "Return" && term.argument
|
|
24203
|
-
|
|
24393
|
+
if (term.kind === "Return" && term.argument) {
|
|
24394
|
+
collectReturnedJSXFromExpression(term.argument, returned);
|
|
24204
24395
|
}
|
|
24205
24396
|
}
|
|
24206
24397
|
}
|
|
24398
|
+
return returned;
|
|
24207
24399
|
}
|
|
24208
24400
|
if (callback.kind === "FunctionExpression") {
|
|
24209
24401
|
for (const block of callback.body ?? []) {
|
|
24210
24402
|
const term = block.terminator;
|
|
24211
|
-
if (term.kind === "Return" && term.argument
|
|
24212
|
-
|
|
24403
|
+
if (term.kind === "Return" && term.argument) {
|
|
24404
|
+
collectReturnedJSXFromExpression(term.argument, returned);
|
|
24213
24405
|
}
|
|
24214
24406
|
}
|
|
24215
24407
|
}
|
|
24216
|
-
return
|
|
24408
|
+
return returned;
|
|
24409
|
+
}
|
|
24410
|
+
function keyExpressionSignature(expression) {
|
|
24411
|
+
try {
|
|
24412
|
+
return JSON.stringify(expression, (key, value) => {
|
|
24413
|
+
if (key === "loc") return void 0;
|
|
24414
|
+
if (typeof value === "bigint") return `__bigint:${value.toString()}`;
|
|
24415
|
+
return value;
|
|
24416
|
+
}) ?? "";
|
|
24417
|
+
} catch {
|
|
24418
|
+
return "";
|
|
24419
|
+
}
|
|
24217
24420
|
}
|
|
24218
24421
|
function extractKeyFromMapCallback(callback) {
|
|
24219
|
-
const
|
|
24220
|
-
if (
|
|
24221
|
-
|
|
24422
|
+
const returnedKeyExpressions = getReturnedKeyExpressionsFromCallback(callback);
|
|
24423
|
+
if (returnedKeyExpressions.length === 1) {
|
|
24424
|
+
return returnedKeyExpressions[0];
|
|
24425
|
+
}
|
|
24426
|
+
if (returnedKeyExpressions.length > 1) {
|
|
24427
|
+
const [firstKey2, ...restKeys2] = returnedKeyExpressions;
|
|
24428
|
+
const firstSignature2 = keyExpressionSignature(firstKey2);
|
|
24429
|
+
if (firstSignature2 && restKeys2.every((keyExpr) => keyExpressionSignature(keyExpr) === firstSignature2)) {
|
|
24430
|
+
return firstKey2;
|
|
24431
|
+
}
|
|
24432
|
+
}
|
|
24433
|
+
const returned = getReturnedJSXFromCallback(callback);
|
|
24434
|
+
if (returned.length === 0) return void 0;
|
|
24435
|
+
const keyExpressions = returned.map((jsx) => extractKeyFromAttributes(jsx.attributes));
|
|
24436
|
+
if (keyExpressions.some((expr) => !expr)) return void 0;
|
|
24437
|
+
const [firstKey, ...restKeys] = keyExpressions;
|
|
24438
|
+
const firstSignature = keyExpressionSignature(firstKey);
|
|
24439
|
+
if (!firstSignature) return void 0;
|
|
24440
|
+
const allBranchesSameKey = restKeys.every(
|
|
24441
|
+
(keyExpr) => keyExpressionSignature(keyExpr) === firstSignature
|
|
24442
|
+
);
|
|
24443
|
+
if (!allBranchesSameKey) return void 0;
|
|
24444
|
+
return firstKey;
|
|
24222
24445
|
}
|
|
24223
24446
|
|
|
24224
24447
|
// src/ir/codegen-overrides.ts
|
|
@@ -24823,6 +25046,15 @@ function buildListCallExpression(expr, statements, ctx, ops) {
|
|
|
24823
25046
|
ctx.inListRender = true;
|
|
24824
25047
|
let callbackExpr = ops.lowerExpression(mapCallback, ctx);
|
|
24825
25048
|
ctx.inListRender = prevInListRender;
|
|
25049
|
+
const shouldDeferOptionalCallbackEvaluation = isOptional && !t4.isArrowFunctionExpression(callbackExpr) && !t4.isFunctionExpression(callbackExpr);
|
|
25050
|
+
let deferredCallbackId = null;
|
|
25051
|
+
let deferredCallbackInitId = null;
|
|
25052
|
+
let deferredItemsId = null;
|
|
25053
|
+
if (shouldDeferOptionalCallbackEvaluation) {
|
|
25054
|
+
deferredCallbackId = ops.genTemp(ctx, "mapCb");
|
|
25055
|
+
deferredCallbackInitId = ops.genTemp(ctx, "mapCbReady");
|
|
25056
|
+
deferredItemsId = ops.genTemp(ctx, "mapItems");
|
|
25057
|
+
}
|
|
24826
25058
|
const capturedKeyParamName = ctx.listKeyParamName;
|
|
24827
25059
|
ctx.listKeyExpr = prevListKeyExpr;
|
|
24828
25060
|
ctx.listItemParamName = prevListItemParamName;
|
|
@@ -24922,7 +25154,7 @@ function buildListCallExpression(expr, statements, ctx, ops) {
|
|
|
24922
25154
|
],
|
|
24923
25155
|
keyExprAst
|
|
24924
25156
|
);
|
|
24925
|
-
const hasIndexParam = (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
25157
|
+
const hasIndexParam = shouldDeferOptionalCallbackEvaluation || (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
24926
25158
|
if (canConstifyKey && (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr))) {
|
|
24927
25159
|
const newParams = [...callbackExpr.params];
|
|
24928
25160
|
while (newParams.length < 2) {
|
|
@@ -24942,25 +25174,131 @@ function buildListCallExpression(expr, statements, ctx, ops) {
|
|
|
24942
25174
|
}
|
|
24943
25175
|
}
|
|
24944
25176
|
statements.push(...hoistedStatements);
|
|
25177
|
+
if (shouldDeferOptionalCallbackEvaluation) {
|
|
25178
|
+
statements.push(
|
|
25179
|
+
t4.variableDeclaration("let", [
|
|
25180
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackId, true))
|
|
25181
|
+
]),
|
|
25182
|
+
t4.variableDeclaration("let", [
|
|
25183
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackInitId, true), t4.booleanLiteral(false))
|
|
25184
|
+
])
|
|
25185
|
+
);
|
|
25186
|
+
}
|
|
25187
|
+
const getItemsExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25188
|
+
[],
|
|
25189
|
+
t4.blockStatement([
|
|
25190
|
+
t4.variableDeclaration("const", [
|
|
25191
|
+
t4.variableDeclarator(
|
|
25192
|
+
t4.cloneNode(deferredItemsId, true),
|
|
25193
|
+
t4.cloneNode(arrayExprBase, true)
|
|
25194
|
+
)
|
|
25195
|
+
]),
|
|
25196
|
+
t4.ifStatement(
|
|
25197
|
+
t4.binaryExpression("==", t4.cloneNode(deferredItemsId, true), t4.nullLiteral()),
|
|
25198
|
+
t4.blockStatement([t4.returnStatement(t4.arrayExpression([]))])
|
|
25199
|
+
),
|
|
25200
|
+
t4.ifStatement(
|
|
25201
|
+
t4.unaryExpression("!", t4.cloneNode(deferredCallbackInitId, true)),
|
|
25202
|
+
t4.blockStatement([
|
|
25203
|
+
t4.expressionStatement(
|
|
25204
|
+
t4.assignmentExpression(
|
|
25205
|
+
"=",
|
|
25206
|
+
t4.cloneNode(deferredCallbackId, true),
|
|
25207
|
+
t4.cloneNode(callbackExpr, true)
|
|
25208
|
+
)
|
|
25209
|
+
),
|
|
25210
|
+
t4.expressionStatement(
|
|
25211
|
+
t4.assignmentExpression(
|
|
25212
|
+
"=",
|
|
25213
|
+
t4.cloneNode(deferredCallbackInitId, true),
|
|
25214
|
+
t4.booleanLiteral(true)
|
|
25215
|
+
)
|
|
25216
|
+
)
|
|
25217
|
+
])
|
|
25218
|
+
),
|
|
25219
|
+
t4.returnStatement(t4.cloneNode(deferredItemsId, true))
|
|
25220
|
+
])
|
|
25221
|
+
) : t4.arrowFunctionExpression([], arrayExpr);
|
|
25222
|
+
const renderExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25223
|
+
[t4.identifier("__item"), t4.identifier("__index"), t4.identifier("__key")],
|
|
25224
|
+
t4.callExpression(t4.cloneNode(deferredCallbackId, true), [
|
|
25225
|
+
t4.identifier("__item"),
|
|
25226
|
+
t4.identifier("__index"),
|
|
25227
|
+
t4.identifier("__key")
|
|
25228
|
+
])
|
|
25229
|
+
) : callbackExpr;
|
|
24945
25230
|
listCall = t4.callExpression(t4.identifier(RUNTIME_ALIASES.keyedList), [
|
|
24946
|
-
|
|
25231
|
+
getItemsExpr,
|
|
24947
25232
|
keyFn,
|
|
24948
|
-
|
|
25233
|
+
renderExpr,
|
|
24949
25234
|
t4.booleanLiteral(hasIndexParam)
|
|
24950
25235
|
]);
|
|
24951
25236
|
} else {
|
|
24952
25237
|
statements.push(...hoistedStatements);
|
|
25238
|
+
if (shouldDeferOptionalCallbackEvaluation) {
|
|
25239
|
+
statements.push(
|
|
25240
|
+
t4.variableDeclaration("let", [
|
|
25241
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackId, true))
|
|
25242
|
+
]),
|
|
25243
|
+
t4.variableDeclaration("let", [
|
|
25244
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackInitId, true), t4.booleanLiteral(false))
|
|
25245
|
+
])
|
|
25246
|
+
);
|
|
25247
|
+
}
|
|
24953
25248
|
const itemParamName = t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr) ? t4.isIdentifier(callbackExpr.params[0]) ? callbackExpr.params[0].name : "__item" : "__item";
|
|
24954
25249
|
const indexParamName = t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr) ? t4.isIdentifier(callbackExpr.params[1]) ? callbackExpr.params[1].name : "__index" : "__index";
|
|
24955
|
-
const hasIndexParam = (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
25250
|
+
const hasIndexParam = shouldDeferOptionalCallbackEvaluation || (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
25251
|
+
const getItemsExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25252
|
+
[],
|
|
25253
|
+
t4.blockStatement([
|
|
25254
|
+
t4.variableDeclaration("const", [
|
|
25255
|
+
t4.variableDeclarator(
|
|
25256
|
+
t4.cloneNode(deferredItemsId, true),
|
|
25257
|
+
t4.cloneNode(arrayExprBase, true)
|
|
25258
|
+
)
|
|
25259
|
+
]),
|
|
25260
|
+
t4.ifStatement(
|
|
25261
|
+
t4.binaryExpression("==", t4.cloneNode(deferredItemsId, true), t4.nullLiteral()),
|
|
25262
|
+
t4.blockStatement([t4.returnStatement(t4.arrayExpression([]))])
|
|
25263
|
+
),
|
|
25264
|
+
t4.ifStatement(
|
|
25265
|
+
t4.unaryExpression("!", t4.cloneNode(deferredCallbackInitId, true)),
|
|
25266
|
+
t4.blockStatement([
|
|
25267
|
+
t4.expressionStatement(
|
|
25268
|
+
t4.assignmentExpression(
|
|
25269
|
+
"=",
|
|
25270
|
+
t4.cloneNode(deferredCallbackId, true),
|
|
25271
|
+
t4.cloneNode(callbackExpr, true)
|
|
25272
|
+
)
|
|
25273
|
+
),
|
|
25274
|
+
t4.expressionStatement(
|
|
25275
|
+
t4.assignmentExpression(
|
|
25276
|
+
"=",
|
|
25277
|
+
t4.cloneNode(deferredCallbackInitId, true),
|
|
25278
|
+
t4.booleanLiteral(true)
|
|
25279
|
+
)
|
|
25280
|
+
)
|
|
25281
|
+
])
|
|
25282
|
+
),
|
|
25283
|
+
t4.returnStatement(t4.cloneNode(deferredItemsId, true))
|
|
25284
|
+
])
|
|
25285
|
+
) : t4.arrowFunctionExpression([], arrayExpr);
|
|
25286
|
+
const renderExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25287
|
+
[t4.identifier("__item"), t4.identifier("__index"), t4.identifier("__key")],
|
|
25288
|
+
t4.callExpression(t4.cloneNode(deferredCallbackId, true), [
|
|
25289
|
+
t4.identifier("__item"),
|
|
25290
|
+
t4.identifier("__index"),
|
|
25291
|
+
t4.identifier("__key")
|
|
25292
|
+
])
|
|
25293
|
+
) : callbackExpr;
|
|
24956
25294
|
const keyFn = t4.arrowFunctionExpression(
|
|
24957
25295
|
[t4.identifier(itemParamName), t4.identifier(indexParamName)],
|
|
24958
25296
|
t4.identifier(indexParamName)
|
|
24959
25297
|
);
|
|
24960
25298
|
listCall = t4.callExpression(t4.identifier(RUNTIME_ALIASES.keyedList), [
|
|
24961
|
-
|
|
25299
|
+
getItemsExpr,
|
|
24962
25300
|
keyFn,
|
|
24963
|
-
|
|
25301
|
+
renderExpr,
|
|
24964
25302
|
t4.booleanLiteral(hasIndexParam)
|
|
24965
25303
|
]);
|
|
24966
25304
|
}
|
|
@@ -26125,8 +26463,31 @@ function extractHIRStaticHtml(jsx, ctx, ops, parentPath = [], namespace = null)
|
|
|
26125
26463
|
const resolvedNamespace = resolveNamespaceContext(tagName, namespace);
|
|
26126
26464
|
let html = `<${tagName}`;
|
|
26127
26465
|
const bindings = [];
|
|
26128
|
-
for (
|
|
26466
|
+
for (let attrIndex = 0; attrIndex < jsx.attributes.length; attrIndex++) {
|
|
26467
|
+
const attr = jsx.attributes[attrIndex];
|
|
26129
26468
|
if (attr.isSpread) {
|
|
26469
|
+
if (attr.spreadExpr) {
|
|
26470
|
+
const excluded = /* @__PURE__ */ new Set();
|
|
26471
|
+
for (let nextIndex = attrIndex + 1; nextIndex < jsx.attributes.length; nextIndex++) {
|
|
26472
|
+
const nextAttr = jsx.attributes[nextIndex];
|
|
26473
|
+
if (nextAttr.isSpread) continue;
|
|
26474
|
+
let nextName = normalizeHIRAttrName(nextAttr.name);
|
|
26475
|
+
if (nextName.endsWith("$")) {
|
|
26476
|
+
nextName = nextName.slice(0, -1);
|
|
26477
|
+
}
|
|
26478
|
+
if (nextName === "key") continue;
|
|
26479
|
+
excluded.add(nextName);
|
|
26480
|
+
if (nextName !== nextAttr.name) {
|
|
26481
|
+
excluded.add(nextAttr.name);
|
|
26482
|
+
}
|
|
26483
|
+
}
|
|
26484
|
+
bindings.push({
|
|
26485
|
+
type: "spread",
|
|
26486
|
+
path: [...parentPath],
|
|
26487
|
+
expr: attr.spreadExpr,
|
|
26488
|
+
exclude: excluded.size > 0 ? Array.from(excluded) : void 0
|
|
26489
|
+
});
|
|
26490
|
+
}
|
|
26130
26491
|
continue;
|
|
26131
26492
|
}
|
|
26132
26493
|
let name = normalizeHIRAttrName(attr.name);
|
|
@@ -28311,10 +28672,28 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
28311
28672
|
)
|
|
28312
28673
|
);
|
|
28313
28674
|
}
|
|
28675
|
+
fusedPatchGroups.clear();
|
|
28314
28676
|
};
|
|
28315
28677
|
for (const binding of bindings) {
|
|
28316
28678
|
const targetId = resolveHIRBindingPath(binding.path, nodeCache, statements, ctx, genTemp3);
|
|
28317
|
-
if (binding.type === "
|
|
28679
|
+
if (binding.type === "spread" && binding.expr) {
|
|
28680
|
+
flushFusedPatchGroups();
|
|
28681
|
+
ctx.helpersUsed.add("spread");
|
|
28682
|
+
const spreadValueExpr = lowerDomExpression(binding.expr, ctx, containingRegion);
|
|
28683
|
+
const spreadGetter = t4.arrowFunctionExpression([], spreadValueExpr);
|
|
28684
|
+
const spreadArgs = [
|
|
28685
|
+
targetId,
|
|
28686
|
+
spreadGetter,
|
|
28687
|
+
t4.booleanLiteral(Boolean(isSVG || isMathML)),
|
|
28688
|
+
t4.booleanLiteral(true)
|
|
28689
|
+
];
|
|
28690
|
+
if (binding.exclude && binding.exclude.length > 0) {
|
|
28691
|
+
spreadArgs.push(t4.arrayExpression(binding.exclude.map((name) => t4.stringLiteral(name))));
|
|
28692
|
+
}
|
|
28693
|
+
statements.push(
|
|
28694
|
+
t4.expressionStatement(t4.callExpression(t4.identifier(RUNTIME_ALIASES.spread), spreadArgs))
|
|
28695
|
+
);
|
|
28696
|
+
} else if (binding.type === "event" && binding.expr && binding.name) {
|
|
28318
28697
|
const eventName = binding.name;
|
|
28319
28698
|
const hasEventOptions = binding.eventOptions && (binding.eventOptions.capture || binding.eventOptions.passive || binding.eventOptions.once);
|
|
28320
28699
|
const isDelegated = DelegatedEvents.has(eventName) && !hasEventOptions;
|
|
@@ -33102,106 +33481,106 @@ function collectUsesFromTerminator(term, add, inFunctionBody = false) {
|
|
|
33102
33481
|
}
|
|
33103
33482
|
}
|
|
33104
33483
|
function collectUsesFromExpression(expr, add, inFunctionBody = false) {
|
|
33105
|
-
|
|
33484
|
+
walkExpression2(expr, add, { inFunctionBody, shadowed: /* @__PURE__ */ new Set() });
|
|
33106
33485
|
}
|
|
33107
|
-
function
|
|
33486
|
+
function walkExpression2(expr, add, ctx) {
|
|
33108
33487
|
switch (expr.kind) {
|
|
33109
33488
|
case "Identifier":
|
|
33110
33489
|
if (!ctx.shadowed.has(expr.name)) add(expr.name, ctx.inFunctionBody);
|
|
33111
33490
|
return;
|
|
33112
33491
|
case "CallExpression":
|
|
33113
33492
|
case "OptionalCallExpression":
|
|
33114
|
-
|
|
33115
|
-
expr.arguments.forEach((arg) =>
|
|
33493
|
+
walkExpression2(expr.callee, add, ctx);
|
|
33494
|
+
expr.arguments.forEach((arg) => walkExpression2(arg, add, ctx));
|
|
33116
33495
|
return;
|
|
33117
33496
|
case "MemberExpression":
|
|
33118
33497
|
case "OptionalMemberExpression":
|
|
33119
|
-
|
|
33120
|
-
if (expr.computed)
|
|
33498
|
+
walkExpression2(expr.object, add, ctx);
|
|
33499
|
+
if (expr.computed) walkExpression2(expr.property, add, ctx);
|
|
33121
33500
|
return;
|
|
33122
33501
|
case "BinaryExpression":
|
|
33123
33502
|
case "LogicalExpression":
|
|
33124
|
-
|
|
33125
|
-
|
|
33503
|
+
walkExpression2(expr.left, add, ctx);
|
|
33504
|
+
walkExpression2(expr.right, add, ctx);
|
|
33126
33505
|
return;
|
|
33127
33506
|
case "UnaryExpression":
|
|
33128
|
-
|
|
33507
|
+
walkExpression2(expr.argument, add, ctx);
|
|
33129
33508
|
return;
|
|
33130
33509
|
case "ConditionalExpression":
|
|
33131
|
-
|
|
33132
|
-
|
|
33133
|
-
|
|
33510
|
+
walkExpression2(expr.test, add, ctx);
|
|
33511
|
+
walkExpression2(expr.consequent, add, ctx);
|
|
33512
|
+
walkExpression2(expr.alternate, add, ctx);
|
|
33134
33513
|
return;
|
|
33135
33514
|
case "ArrayExpression":
|
|
33136
33515
|
expr.elements.forEach((el) => {
|
|
33137
|
-
if (el)
|
|
33516
|
+
if (el) walkExpression2(el, add, ctx);
|
|
33138
33517
|
});
|
|
33139
33518
|
return;
|
|
33140
33519
|
case "ObjectExpression":
|
|
33141
33520
|
expr.properties.forEach((prop) => {
|
|
33142
33521
|
if (prop.kind === "SpreadElement") {
|
|
33143
|
-
|
|
33522
|
+
walkExpression2(prop.argument, add, ctx);
|
|
33144
33523
|
} else {
|
|
33145
|
-
if (prop.computed)
|
|
33146
|
-
|
|
33524
|
+
if (prop.computed) walkExpression2(prop.key, add, ctx);
|
|
33525
|
+
walkExpression2(prop.value, add, ctx);
|
|
33147
33526
|
}
|
|
33148
33527
|
});
|
|
33149
33528
|
return;
|
|
33150
33529
|
case "TemplateLiteral":
|
|
33151
|
-
expr.expressions.forEach((e) =>
|
|
33530
|
+
expr.expressions.forEach((e) => walkExpression2(e, add, ctx));
|
|
33152
33531
|
return;
|
|
33153
33532
|
case "SpreadElement":
|
|
33154
|
-
|
|
33533
|
+
walkExpression2(expr.argument, add, ctx);
|
|
33155
33534
|
return;
|
|
33156
33535
|
case "SequenceExpression":
|
|
33157
|
-
expr.expressions.forEach((e) =>
|
|
33536
|
+
expr.expressions.forEach((e) => walkExpression2(e, add, ctx));
|
|
33158
33537
|
return;
|
|
33159
33538
|
case "AwaitExpression":
|
|
33160
|
-
|
|
33539
|
+
walkExpression2(expr.argument, add, ctx);
|
|
33161
33540
|
return;
|
|
33162
33541
|
case "NewExpression":
|
|
33163
|
-
|
|
33164
|
-
expr.arguments.forEach((arg) =>
|
|
33542
|
+
walkExpression2(expr.callee, add, ctx);
|
|
33543
|
+
expr.arguments.forEach((arg) => walkExpression2(arg, add, ctx));
|
|
33165
33544
|
return;
|
|
33166
33545
|
case "ArrowFunction": {
|
|
33167
33546
|
const shadowed = new Set(ctx.shadowed);
|
|
33168
33547
|
expr.params.forEach((p) => shadowed.add(p.name));
|
|
33169
33548
|
if (expr.isExpression) {
|
|
33170
|
-
|
|
33549
|
+
walkExpression2(expr.body, add, { inFunctionBody: true, shadowed });
|
|
33171
33550
|
return;
|
|
33172
33551
|
}
|
|
33173
|
-
|
|
33552
|
+
walkBlocks2(expr.body, add, { inFunctionBody: true, shadowed });
|
|
33174
33553
|
return;
|
|
33175
33554
|
}
|
|
33176
33555
|
case "FunctionExpression": {
|
|
33177
33556
|
const shadowed = new Set(ctx.shadowed);
|
|
33178
33557
|
expr.params.forEach((p) => shadowed.add(p.name));
|
|
33179
|
-
|
|
33558
|
+
walkBlocks2(expr.body, add, { inFunctionBody: true, shadowed });
|
|
33180
33559
|
return;
|
|
33181
33560
|
}
|
|
33182
33561
|
case "AssignmentExpression":
|
|
33183
|
-
|
|
33184
|
-
|
|
33562
|
+
walkExpression2(expr.left, add, ctx);
|
|
33563
|
+
walkExpression2(expr.right, add, ctx);
|
|
33185
33564
|
return;
|
|
33186
33565
|
case "UpdateExpression":
|
|
33187
|
-
|
|
33566
|
+
walkExpression2(expr.argument, add, ctx);
|
|
33188
33567
|
return;
|
|
33189
33568
|
case "JSXElement":
|
|
33190
33569
|
if (typeof expr.tagName !== "string") {
|
|
33191
|
-
|
|
33570
|
+
walkExpression2(expr.tagName, add, ctx);
|
|
33192
33571
|
}
|
|
33193
33572
|
expr.attributes.forEach((attr) => {
|
|
33194
33573
|
if (attr.isSpread && attr.spreadExpr) {
|
|
33195
|
-
|
|
33574
|
+
walkExpression2(attr.spreadExpr, add, ctx);
|
|
33196
33575
|
} else if (attr.value) {
|
|
33197
|
-
|
|
33576
|
+
walkExpression2(attr.value, add, ctx);
|
|
33198
33577
|
}
|
|
33199
33578
|
});
|
|
33200
33579
|
expr.children.forEach((child) => {
|
|
33201
33580
|
if (child.kind === "expression") {
|
|
33202
|
-
|
|
33581
|
+
walkExpression2(child.value, add, ctx);
|
|
33203
33582
|
} else if (child.kind === "element") {
|
|
33204
|
-
|
|
33583
|
+
walkExpression2(child.value, add, ctx);
|
|
33205
33584
|
}
|
|
33206
33585
|
});
|
|
33207
33586
|
return;
|
|
@@ -33209,16 +33588,16 @@ function walkExpression(expr, add, ctx) {
|
|
|
33209
33588
|
return;
|
|
33210
33589
|
}
|
|
33211
33590
|
}
|
|
33212
|
-
function
|
|
33591
|
+
function walkBlocks2(blocks, add, ctx) {
|
|
33213
33592
|
for (const block of blocks) {
|
|
33214
33593
|
for (const instr of block.instructions) {
|
|
33215
33594
|
if (instr.kind === "Assign") {
|
|
33216
|
-
|
|
33595
|
+
walkExpression2(instr.value, add, ctx);
|
|
33217
33596
|
if (instr.declarationKind) {
|
|
33218
33597
|
ctx.shadowed.add(instr.target.name);
|
|
33219
33598
|
}
|
|
33220
33599
|
} else if (instr.kind === "Expression") {
|
|
33221
|
-
|
|
33600
|
+
walkExpression2(instr.value, add, ctx);
|
|
33222
33601
|
} else if (instr.kind === "Phi") {
|
|
33223
33602
|
instr.sources.forEach((src) => {
|
|
33224
33603
|
if (!ctx.shadowed.has(src.id.name)) add(src.id.name, ctx.inFunctionBody);
|
|
@@ -33237,7 +33616,7 @@ function walkBlocks(blocks, add, ctx) {
|
|
|
33237
33616
|
function collectExpressionIdentifiers2(expr, deep = false) {
|
|
33238
33617
|
const deps = /* @__PURE__ */ new Set();
|
|
33239
33618
|
const collect = (name) => deps.add(name);
|
|
33240
|
-
|
|
33619
|
+
walkExpression2(expr, (name, _inFunctionBody) => collect(name), {
|
|
33241
33620
|
inFunctionBody: deep,
|
|
33242
33621
|
shadowed: /* @__PURE__ */ new Set()
|
|
33243
33622
|
});
|
|
@@ -33818,6 +34197,506 @@ function getRootIdentifier(expr, t4) {
|
|
|
33818
34197
|
return null;
|
|
33819
34198
|
}
|
|
33820
34199
|
|
|
34200
|
+
// src/tooling/analyze.ts
|
|
34201
|
+
var import_core2 = require("@babel/core");
|
|
34202
|
+
|
|
34203
|
+
// src/tooling/trace-infer.ts
|
|
34204
|
+
var TRACE_REGEX_ESCAPES = /[.*+?^${}()|[\]\\]/g;
|
|
34205
|
+
var IDENTIFIER_NAME = /^[A-Za-z_$][\w$]*$/;
|
|
34206
|
+
function isIdentifierName(name) {
|
|
34207
|
+
return IDENTIFIER_NAME.test(name);
|
|
34208
|
+
}
|
|
34209
|
+
function lineContainsIdentifier(lineText, identifier2) {
|
|
34210
|
+
const pattern = new RegExp(`\\b${identifier2.replace(TRACE_REGEX_ESCAPES, "\\$&")}\\b`);
|
|
34211
|
+
return pattern.test(lineText);
|
|
34212
|
+
}
|
|
34213
|
+
function lineContainsAnyIdentifier(lineText, identifiers) {
|
|
34214
|
+
for (const id of identifiers) {
|
|
34215
|
+
if (lineContainsIdentifier(lineText, id)) return true;
|
|
34216
|
+
}
|
|
34217
|
+
return false;
|
|
34218
|
+
}
|
|
34219
|
+
function pushTraceMarker(markersByLine, line, marker) {
|
|
34220
|
+
const markers = markersByLine.get(line);
|
|
34221
|
+
if (!markers) {
|
|
34222
|
+
markersByLine.set(line, [marker]);
|
|
34223
|
+
return;
|
|
34224
|
+
}
|
|
34225
|
+
const duplicate = markers.some(
|
|
34226
|
+
(existing) => existing.kind === marker.kind && existing.label === marker.label
|
|
34227
|
+
);
|
|
34228
|
+
if (!duplicate) markers.push(marker);
|
|
34229
|
+
}
|
|
34230
|
+
function inferReactiveLocalNames(startLine, endLine, sourceLines, baseReactiveNames) {
|
|
34231
|
+
const reactiveNames = new Set(baseReactiveNames);
|
|
34232
|
+
const declarationLines = [];
|
|
34233
|
+
const declarationPattern = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(.+?)(?:;)?$/;
|
|
34234
|
+
for (let line = startLine; line <= endLine; line++) {
|
|
34235
|
+
const text = (sourceLines[line - 1] ?? "").trim();
|
|
34236
|
+
if (!text) continue;
|
|
34237
|
+
const withoutComment = text.replace(/\/\/.*$/, "").trim();
|
|
34238
|
+
if (!withoutComment) continue;
|
|
34239
|
+
const match = withoutComment.match(declarationPattern);
|
|
34240
|
+
if (!match) continue;
|
|
34241
|
+
const name = match[1];
|
|
34242
|
+
const expression = match[2];
|
|
34243
|
+
if (!name || !expression) continue;
|
|
34244
|
+
declarationLines.push({ name, expression });
|
|
34245
|
+
}
|
|
34246
|
+
let changed = true;
|
|
34247
|
+
while (changed) {
|
|
34248
|
+
changed = false;
|
|
34249
|
+
for (const declaration of declarationLines) {
|
|
34250
|
+
if (reactiveNames.has(declaration.name)) continue;
|
|
34251
|
+
if (!lineContainsAnyIdentifier(declaration.expression, reactiveNames)) continue;
|
|
34252
|
+
reactiveNames.add(declaration.name);
|
|
34253
|
+
changed = true;
|
|
34254
|
+
}
|
|
34255
|
+
}
|
|
34256
|
+
return reactiveNames;
|
|
34257
|
+
}
|
|
34258
|
+
function isStateCallInstruction(instr) {
|
|
34259
|
+
if (instr.kind !== "Assign") return false;
|
|
34260
|
+
const value = instr.value;
|
|
34261
|
+
return value.kind === "CallExpression" && value.callee.kind === "Identifier" && value.callee.name === "$state";
|
|
34262
|
+
}
|
|
34263
|
+
function collectStateDeclNames(fn) {
|
|
34264
|
+
const result = [];
|
|
34265
|
+
for (const block of fn.blocks) {
|
|
34266
|
+
for (const instr of block.instructions) {
|
|
34267
|
+
if (!isStateCallInstruction(instr) || !instr.loc) continue;
|
|
34268
|
+
const name = deSSAVarName(instr.target.name);
|
|
34269
|
+
if (!isIdentifierName(name)) continue;
|
|
34270
|
+
result.push({ name, line: instr.loc.start.line });
|
|
34271
|
+
}
|
|
34272
|
+
}
|
|
34273
|
+
return result;
|
|
34274
|
+
}
|
|
34275
|
+
function expressionContainsEffectCall(instr) {
|
|
34276
|
+
const value = instr.kind === "Assign" || instr.kind === "Expression" ? instr.value : null;
|
|
34277
|
+
if (!value || !instr.loc) return null;
|
|
34278
|
+
let found = false;
|
|
34279
|
+
walkExpression(value, (expr) => {
|
|
34280
|
+
if (expr.kind === "CallExpression" && expr.callee.kind === "Identifier" && deSSAVarName(expr.callee.name) === "$effect") {
|
|
34281
|
+
found = true;
|
|
34282
|
+
}
|
|
34283
|
+
});
|
|
34284
|
+
return found ? instr.loc.start.line : null;
|
|
34285
|
+
}
|
|
34286
|
+
function flattenRegions2(regions) {
|
|
34287
|
+
if (!regions || regions.length === 0) return [];
|
|
34288
|
+
const result = [];
|
|
34289
|
+
const visit = (region) => {
|
|
34290
|
+
result.push(region);
|
|
34291
|
+
region.children?.forEach((child) => visit(child));
|
|
34292
|
+
};
|
|
34293
|
+
regions.forEach((region) => visit(region));
|
|
34294
|
+
return result;
|
|
34295
|
+
}
|
|
34296
|
+
function findContainingRegion2(line, flatRegions) {
|
|
34297
|
+
let best;
|
|
34298
|
+
for (const region of flatRegions) {
|
|
34299
|
+
if (region.startLine === void 0 || region.endLine === void 0 || line < region.startLine || line > region.endLine) {
|
|
34300
|
+
continue;
|
|
34301
|
+
}
|
|
34302
|
+
const bestSpan = best && best.startLine !== void 0 && best.endLine !== void 0 ? best.endLine - best.startLine : Number.POSITIVE_INFINITY;
|
|
34303
|
+
const span = region.endLine - region.startLine;
|
|
34304
|
+
if (span <= bestSpan) best = region;
|
|
34305
|
+
}
|
|
34306
|
+
return best;
|
|
34307
|
+
}
|
|
34308
|
+
function inferTraceMarkersForComponent(input) {
|
|
34309
|
+
const { fn, sourceLines, startLine, endLine, verbosity, regions } = input;
|
|
34310
|
+
const markersByLine = /* @__PURE__ */ new Map();
|
|
34311
|
+
pushTraceMarker(markersByLine, startLine, {
|
|
34312
|
+
kind: "once",
|
|
34313
|
+
label: "Component setup runs on mount"
|
|
34314
|
+
});
|
|
34315
|
+
const stateDecls = collectStateDeclNames(fn);
|
|
34316
|
+
const reactiveNames = inferReactiveLocalNames(
|
|
34317
|
+
startLine,
|
|
34318
|
+
endLine,
|
|
34319
|
+
sourceLines,
|
|
34320
|
+
stateDecls.map((item) => item.name)
|
|
34321
|
+
);
|
|
34322
|
+
for (const stateDecl of stateDecls) {
|
|
34323
|
+
pushTraceMarker(markersByLine, stateDecl.line, {
|
|
34324
|
+
kind: "once",
|
|
34325
|
+
label: "Signal initialization runs once"
|
|
34326
|
+
});
|
|
34327
|
+
}
|
|
34328
|
+
for (const block of fn.blocks) {
|
|
34329
|
+
for (const instr of block.instructions) {
|
|
34330
|
+
const line = expressionContainsEffectCall(instr);
|
|
34331
|
+
if (!line || line < startLine || line > endLine) continue;
|
|
34332
|
+
pushTraceMarker(markersByLine, line, {
|
|
34333
|
+
kind: "effect",
|
|
34334
|
+
label: "Effect reruns when dependencies change"
|
|
34335
|
+
});
|
|
34336
|
+
}
|
|
34337
|
+
}
|
|
34338
|
+
const flatRegions = flattenRegions2(regions);
|
|
34339
|
+
for (let line = startLine; line <= endLine; line++) {
|
|
34340
|
+
const lineText = sourceLines[line - 1] ?? "";
|
|
34341
|
+
if (!lineText) continue;
|
|
34342
|
+
const hasReactiveName = lineContainsAnyIdentifier(lineText, reactiveNames);
|
|
34343
|
+
if (hasReactiveName && /\{[^}]*\b[A-Za-z_$][\w$]*\b[^}]*\}/.test(lineText)) {
|
|
34344
|
+
pushTraceMarker(markersByLine, line, {
|
|
34345
|
+
kind: "reactive",
|
|
34346
|
+
label: "JSX expression updates with reactive values"
|
|
34347
|
+
});
|
|
34348
|
+
}
|
|
34349
|
+
if (hasReactiveName && /\bconsole\.(?:log|debug|info|warn|error)\s*\(/.test(lineText)) {
|
|
34350
|
+
pushTraceMarker(markersByLine, line, {
|
|
34351
|
+
kind: "reactive",
|
|
34352
|
+
label: "Statement reruns when reactive values change"
|
|
34353
|
+
});
|
|
34354
|
+
}
|
|
34355
|
+
if (/\b(?:\$effect|effect)\s*\(/.test(lineText)) {
|
|
34356
|
+
pushTraceMarker(markersByLine, line, {
|
|
34357
|
+
kind: "effect",
|
|
34358
|
+
label: "Effect callback executes reactively"
|
|
34359
|
+
});
|
|
34360
|
+
}
|
|
34361
|
+
if (verbosity === "verbose" && !hasReactiveName && /\{[^}]*\}/.test(lineText)) {
|
|
34362
|
+
pushTraceMarker(markersByLine, line, {
|
|
34363
|
+
kind: "once",
|
|
34364
|
+
label: "JSX expression runs during setup only"
|
|
34365
|
+
});
|
|
34366
|
+
}
|
|
34367
|
+
if (/\bconsole\.(?:log|debug|info|warn|error)\s*\(/.test(lineText) && !hasReactiveName && line !== startLine) {
|
|
34368
|
+
pushTraceMarker(markersByLine, line, {
|
|
34369
|
+
kind: "once",
|
|
34370
|
+
label: "Statement runs only during setup"
|
|
34371
|
+
});
|
|
34372
|
+
}
|
|
34373
|
+
const containingRegion = findContainingRegion2(line, flatRegions);
|
|
34374
|
+
if (!containingRegion) continue;
|
|
34375
|
+
const markers = markersByLine.get(line);
|
|
34376
|
+
if (!markers) continue;
|
|
34377
|
+
for (const marker of markers) {
|
|
34378
|
+
marker.regionId = containingRegion.id;
|
|
34379
|
+
marker.deps = containingRegion.dependencies;
|
|
34380
|
+
}
|
|
34381
|
+
}
|
|
34382
|
+
return [...markersByLine.entries()].sort((a, b) => a[0] - b[0]).map(([line, markers]) => ({ line, markers }));
|
|
34383
|
+
}
|
|
34384
|
+
|
|
34385
|
+
// src/tooling/analyze.ts
|
|
34386
|
+
function mergeLoc(a, b) {
|
|
34387
|
+
if (!a) return b ?? null;
|
|
34388
|
+
if (!b) return a;
|
|
34389
|
+
const start = b.start.line < a.start.line || b.start.line === a.start.line && b.start.column < a.start.column ? b.start : a.start;
|
|
34390
|
+
const end = b.end.line > a.end.line || b.end.line === a.end.line && b.end.column > a.end.column ? b.end : a.end;
|
|
34391
|
+
return {
|
|
34392
|
+
start,
|
|
34393
|
+
end,
|
|
34394
|
+
filename: a.filename ?? b.filename,
|
|
34395
|
+
identifierName: a.identifierName ?? b.identifierName
|
|
34396
|
+
};
|
|
34397
|
+
}
|
|
34398
|
+
function expressionContainsMacroCall(expr, macroName) {
|
|
34399
|
+
let found = false;
|
|
34400
|
+
const visit = (value) => {
|
|
34401
|
+
if (found) return;
|
|
34402
|
+
if (value.kind === "CallExpression" && value.callee.kind === "Identifier" && deSSAVarName(value.callee.name) === macroName) {
|
|
34403
|
+
found = true;
|
|
34404
|
+
return;
|
|
34405
|
+
}
|
|
34406
|
+
switch (value.kind) {
|
|
34407
|
+
case "CallExpression":
|
|
34408
|
+
case "OptionalCallExpression":
|
|
34409
|
+
visit(value.callee);
|
|
34410
|
+
value.arguments.forEach((arg) => visit(arg));
|
|
34411
|
+
return;
|
|
34412
|
+
case "MemberExpression":
|
|
34413
|
+
case "OptionalMemberExpression":
|
|
34414
|
+
visit(value.object);
|
|
34415
|
+
if (value.computed) visit(value.property);
|
|
34416
|
+
return;
|
|
34417
|
+
case "BinaryExpression":
|
|
34418
|
+
case "LogicalExpression":
|
|
34419
|
+
visit(value.left);
|
|
34420
|
+
visit(value.right);
|
|
34421
|
+
return;
|
|
34422
|
+
case "UnaryExpression":
|
|
34423
|
+
case "AwaitExpression":
|
|
34424
|
+
case "UpdateExpression":
|
|
34425
|
+
case "SpreadElement":
|
|
34426
|
+
visit(value.argument);
|
|
34427
|
+
return;
|
|
34428
|
+
case "ConditionalExpression":
|
|
34429
|
+
visit(value.test);
|
|
34430
|
+
visit(value.consequent);
|
|
34431
|
+
visit(value.alternate);
|
|
34432
|
+
return;
|
|
34433
|
+
case "ArrayExpression":
|
|
34434
|
+
value.elements.forEach((el) => visit(el));
|
|
34435
|
+
return;
|
|
34436
|
+
case "ObjectExpression":
|
|
34437
|
+
value.properties.forEach((prop) => {
|
|
34438
|
+
if (prop.kind === "SpreadElement") {
|
|
34439
|
+
visit(prop.argument);
|
|
34440
|
+
return;
|
|
34441
|
+
}
|
|
34442
|
+
if (prop.computed) visit(prop.key);
|
|
34443
|
+
visit(prop.value);
|
|
34444
|
+
});
|
|
34445
|
+
return;
|
|
34446
|
+
case "TemplateLiteral":
|
|
34447
|
+
value.expressions.forEach((item) => visit(item));
|
|
34448
|
+
return;
|
|
34449
|
+
case "AssignmentExpression":
|
|
34450
|
+
visit(value.left);
|
|
34451
|
+
visit(value.right);
|
|
34452
|
+
return;
|
|
34453
|
+
case "SequenceExpression":
|
|
34454
|
+
value.expressions.forEach((item) => visit(item));
|
|
34455
|
+
return;
|
|
34456
|
+
case "YieldExpression":
|
|
34457
|
+
if (value.argument) visit(value.argument);
|
|
34458
|
+
return;
|
|
34459
|
+
case "TaggedTemplateExpression":
|
|
34460
|
+
visit(value.tag);
|
|
34461
|
+
value.quasi.expressions.forEach((item) => visit(item));
|
|
34462
|
+
return;
|
|
34463
|
+
case "ImportExpression":
|
|
34464
|
+
visit(value.source);
|
|
34465
|
+
return;
|
|
34466
|
+
case "ArrowFunction":
|
|
34467
|
+
if (Array.isArray(value.body)) {
|
|
34468
|
+
value.body.forEach((block) => {
|
|
34469
|
+
block.instructions.forEach((instr) => {
|
|
34470
|
+
if (instr.kind === "Assign" || instr.kind === "Expression") {
|
|
34471
|
+
visit(instr.value);
|
|
34472
|
+
}
|
|
34473
|
+
});
|
|
34474
|
+
});
|
|
34475
|
+
} else {
|
|
34476
|
+
visit(value.body);
|
|
34477
|
+
}
|
|
34478
|
+
return;
|
|
34479
|
+
case "FunctionExpression":
|
|
34480
|
+
value.body.forEach((block) => {
|
|
34481
|
+
block.instructions.forEach((instr) => {
|
|
34482
|
+
if (instr.kind === "Assign" || instr.kind === "Expression") {
|
|
34483
|
+
visit(instr.value);
|
|
34484
|
+
}
|
|
34485
|
+
});
|
|
34486
|
+
});
|
|
34487
|
+
return;
|
|
34488
|
+
case "JSXElement":
|
|
34489
|
+
if (typeof value.tagName !== "string") visit(value.tagName);
|
|
34490
|
+
value.attributes.forEach((attr) => {
|
|
34491
|
+
if (attr.isSpread && attr.spreadExpr) {
|
|
34492
|
+
visit(attr.spreadExpr);
|
|
34493
|
+
} else if (attr.value) {
|
|
34494
|
+
visit(attr.value);
|
|
34495
|
+
}
|
|
34496
|
+
});
|
|
34497
|
+
value.children.forEach((child) => {
|
|
34498
|
+
if (child.kind === "expression") visit(child.value);
|
|
34499
|
+
if (child.kind === "element") visit(child.value);
|
|
34500
|
+
});
|
|
34501
|
+
return;
|
|
34502
|
+
case "Identifier":
|
|
34503
|
+
case "Literal":
|
|
34504
|
+
case "MetaProperty":
|
|
34505
|
+
case "NewExpression":
|
|
34506
|
+
case "ClassExpression":
|
|
34507
|
+
case "ThisExpression":
|
|
34508
|
+
case "SuperExpression":
|
|
34509
|
+
if (value.kind === "NewExpression") {
|
|
34510
|
+
visit(value.callee);
|
|
34511
|
+
value.arguments.forEach((arg) => visit(arg));
|
|
34512
|
+
}
|
|
34513
|
+
if (value.kind === "ClassExpression" && value.superClass) visit(value.superClass);
|
|
34514
|
+
return;
|
|
34515
|
+
default:
|
|
34516
|
+
return;
|
|
34517
|
+
}
|
|
34518
|
+
};
|
|
34519
|
+
visit(expr);
|
|
34520
|
+
return found;
|
|
34521
|
+
}
|
|
34522
|
+
function instructionContainsMacroCall(instruction, macroName) {
|
|
34523
|
+
if (instruction.kind !== "Assign" && instruction.kind !== "Expression") return false;
|
|
34524
|
+
return expressionContainsMacroCall(instruction.value, macroName);
|
|
34525
|
+
}
|
|
34526
|
+
function functionUsesMacro(fn, macroName) {
|
|
34527
|
+
for (const block of fn.blocks) {
|
|
34528
|
+
for (const instruction of block.instructions) {
|
|
34529
|
+
if (instructionContainsMacroCall(instruction, macroName)) return true;
|
|
34530
|
+
}
|
|
34531
|
+
const term = block.terminator;
|
|
34532
|
+
if ("argument" in term && term.argument && expressionContainsMacroCall(term.argument, macroName)) {
|
|
34533
|
+
return true;
|
|
34534
|
+
}
|
|
34535
|
+
if (term.kind === "Branch" && expressionContainsMacroCall(term.test, macroName)) {
|
|
34536
|
+
return true;
|
|
34537
|
+
}
|
|
34538
|
+
if (term.kind === "Switch") {
|
|
34539
|
+
if (expressionContainsMacroCall(term.discriminant, macroName)) return true;
|
|
34540
|
+
if (term.cases.some((entry) => entry.test && expressionContainsMacroCall(entry.test, macroName))) {
|
|
34541
|
+
return true;
|
|
34542
|
+
}
|
|
34543
|
+
}
|
|
34544
|
+
}
|
|
34545
|
+
return false;
|
|
34546
|
+
}
|
|
34547
|
+
function computeRegionLoc(region, fn) {
|
|
34548
|
+
let loc = null;
|
|
34549
|
+
for (const instruction of region.instructions) {
|
|
34550
|
+
loc = mergeLoc(loc, instruction.loc);
|
|
34551
|
+
}
|
|
34552
|
+
for (const blockId of region.blocks) {
|
|
34553
|
+
const block = fn.blocks.find((entry) => entry.id === blockId);
|
|
34554
|
+
if (!block) continue;
|
|
34555
|
+
loc = mergeLoc(loc, block.terminator.loc);
|
|
34556
|
+
}
|
|
34557
|
+
return loc;
|
|
34558
|
+
}
|
|
34559
|
+
function regionToSerializable(region, fn) {
|
|
34560
|
+
const loc = computeRegionLoc(region, fn);
|
|
34561
|
+
return {
|
|
34562
|
+
id: region.id,
|
|
34563
|
+
startLine: loc?.start.line,
|
|
34564
|
+
startColumn: loc?.start.column,
|
|
34565
|
+
endLine: loc?.end.line,
|
|
34566
|
+
endColumn: loc?.end.column,
|
|
34567
|
+
dependencies: [...region.dependencies].map(deSSAVarName),
|
|
34568
|
+
declarations: [...region.declarations].map(deSSAVarName),
|
|
34569
|
+
hasControlFlow: region.hasControlFlow,
|
|
34570
|
+
hasReactiveWrites: region.declarations.size > 0,
|
|
34571
|
+
children: region.children.map((child) => regionToSerializable(child, fn))
|
|
34572
|
+
};
|
|
34573
|
+
}
|
|
34574
|
+
function warningSeverity(code) {
|
|
34575
|
+
const diagnosticCodes = new Set(getAllDiagnosticCodes());
|
|
34576
|
+
if (!diagnosticCodes.has(code)) return "warning" /* Warning */;
|
|
34577
|
+
return getDiagnosticInfo(code).severity;
|
|
34578
|
+
}
|
|
34579
|
+
function normalizeWarningToDiagnostic(warning) {
|
|
34580
|
+
return {
|
|
34581
|
+
code: warning.code,
|
|
34582
|
+
message: warning.message,
|
|
34583
|
+
severity: warningSeverity(warning.code),
|
|
34584
|
+
line: warning.line,
|
|
34585
|
+
column: warning.column
|
|
34586
|
+
};
|
|
34587
|
+
}
|
|
34588
|
+
function normalizeThrownError(error) {
|
|
34589
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
34590
|
+
return {
|
|
34591
|
+
code: "FICT-COMPILE",
|
|
34592
|
+
message,
|
|
34593
|
+
severity: "error" /* Error */,
|
|
34594
|
+
line: 0,
|
|
34595
|
+
column: 0
|
|
34596
|
+
};
|
|
34597
|
+
}
|
|
34598
|
+
function analyzeDiagnostics(code, fileName, options) {
|
|
34599
|
+
const warnings = [];
|
|
34600
|
+
const pluginOptions = {
|
|
34601
|
+
dev: true,
|
|
34602
|
+
filename: fileName,
|
|
34603
|
+
emitModuleMetadata: false,
|
|
34604
|
+
strictGuarantee: false,
|
|
34605
|
+
warningLevels: {
|
|
34606
|
+
...options.compilerOptions?.warningLevels ?? {},
|
|
34607
|
+
"FICT-R004": "warn"
|
|
34608
|
+
},
|
|
34609
|
+
...options.compilerOptions,
|
|
34610
|
+
onWarn: (warning) => warnings.push(warning)
|
|
34611
|
+
};
|
|
34612
|
+
try {
|
|
34613
|
+
(0, import_core2.transformSync)(code, {
|
|
34614
|
+
filename: fileName,
|
|
34615
|
+
configFile: false,
|
|
34616
|
+
babelrc: false,
|
|
34617
|
+
sourceType: "module",
|
|
34618
|
+
parserOpts: {
|
|
34619
|
+
sourceType: "module",
|
|
34620
|
+
plugins: ["typescript", "jsx"],
|
|
34621
|
+
allowReturnOutsideFunction: true
|
|
34622
|
+
},
|
|
34623
|
+
plugins: [[index_default, pluginOptions]],
|
|
34624
|
+
generatorOpts: {
|
|
34625
|
+
compact: false
|
|
34626
|
+
}
|
|
34627
|
+
});
|
|
34628
|
+
} catch (error) {
|
|
34629
|
+
return [...warnings.map(normalizeWarningToDiagnostic), normalizeThrownError(error)];
|
|
34630
|
+
}
|
|
34631
|
+
return warnings.map(normalizeWarningToDiagnostic);
|
|
34632
|
+
}
|
|
34633
|
+
function shouldIncludeFunction(fn) {
|
|
34634
|
+
return functionContainsJSX(fn) || functionUsesMacro(fn, "$state") || functionUsesMacro(fn, "$effect");
|
|
34635
|
+
}
|
|
34636
|
+
function parseFileAst(code, fileName) {
|
|
34637
|
+
const ast = (0, import_core2.parseSync)(code, {
|
|
34638
|
+
filename: fileName,
|
|
34639
|
+
sourceType: "module",
|
|
34640
|
+
parserOpts: {
|
|
34641
|
+
sourceType: "module",
|
|
34642
|
+
plugins: ["typescript", "jsx"],
|
|
34643
|
+
allowReturnOutsideFunction: true
|
|
34644
|
+
}
|
|
34645
|
+
});
|
|
34646
|
+
if (!ast || ast.type !== "File") {
|
|
34647
|
+
throw new Error("Failed to parse source file for Fict analysis.");
|
|
34648
|
+
}
|
|
34649
|
+
return ast;
|
|
34650
|
+
}
|
|
34651
|
+
function analyzeFictFile(code, fileName, options = {}) {
|
|
34652
|
+
const includeRegions = options.includeRegions ?? true;
|
|
34653
|
+
const includeDiagnostics = options.includeDiagnostics ?? true;
|
|
34654
|
+
const verbosity = options.verbosity ?? "minimal";
|
|
34655
|
+
const ast = parseFileAst(code, fileName);
|
|
34656
|
+
const hir = buildHIR(
|
|
34657
|
+
ast,
|
|
34658
|
+
{
|
|
34659
|
+
state: /* @__PURE__ */ new Set(["$state"]),
|
|
34660
|
+
effect: /* @__PURE__ */ new Set(["$effect"])
|
|
34661
|
+
},
|
|
34662
|
+
{
|
|
34663
|
+
dev: true,
|
|
34664
|
+
fileName
|
|
34665
|
+
}
|
|
34666
|
+
);
|
|
34667
|
+
const sourceLines = code.split(/\r?\n/);
|
|
34668
|
+
const components = [];
|
|
34669
|
+
for (const fn of hir.functions) {
|
|
34670
|
+
if (!fn.loc || !shouldIncludeFunction(fn)) continue;
|
|
34671
|
+
const startLine = fn.loc.start.line;
|
|
34672
|
+
const endLine = fn.loc.end.line;
|
|
34673
|
+
const scopeResult = analyzeReactiveScopesWithSSA(fn);
|
|
34674
|
+
const regionResult = generateRegions(fn, scopeResult);
|
|
34675
|
+
const regions = includeRegions ? regionResult.topLevelRegions.map((region) => regionToSerializable(region, fn)) : void 0;
|
|
34676
|
+
const trace = inferTraceMarkersForComponent({
|
|
34677
|
+
fn,
|
|
34678
|
+
sourceLines,
|
|
34679
|
+
startLine,
|
|
34680
|
+
endLine,
|
|
34681
|
+
verbosity,
|
|
34682
|
+
regions
|
|
34683
|
+
});
|
|
34684
|
+
components.push({
|
|
34685
|
+
name: fn.name ?? "<anonymous>",
|
|
34686
|
+
startLine,
|
|
34687
|
+
endLine,
|
|
34688
|
+
trace,
|
|
34689
|
+
regions
|
|
34690
|
+
});
|
|
34691
|
+
}
|
|
34692
|
+
const diagnostics = includeDiagnostics ? analyzeDiagnostics(code, fileName, options) : [];
|
|
34693
|
+
return {
|
|
34694
|
+
fileName,
|
|
34695
|
+
components,
|
|
34696
|
+
diagnostics
|
|
34697
|
+
};
|
|
34698
|
+
}
|
|
34699
|
+
|
|
33821
34700
|
// src/index.ts
|
|
33822
34701
|
function stripMacroImports(path2, t4) {
|
|
33823
34702
|
path2.traverse({
|
|
@@ -34711,46 +35590,77 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
34711
35590
|
path2.traverse({
|
|
34712
35591
|
JSXExpressionContainer(exprPath) {
|
|
34713
35592
|
const expr = exprPath.node.expression;
|
|
34714
|
-
if (!t4.isCallExpression(expr)) return;
|
|
34715
|
-
if (!t4.isMemberExpression(expr.callee) || !t4.isIdentifier(expr.callee.property, { name: "map" })) {
|
|
35593
|
+
if (!t4.isCallExpression(expr) && !t4.isOptionalCallExpression(expr)) return;
|
|
35594
|
+
if (!t4.isMemberExpression(expr.callee) && !t4.isOptionalMemberExpression(expr.callee) || !t4.isIdentifier(expr.callee.property, { name: "map" })) {
|
|
34716
35595
|
return;
|
|
34717
35596
|
}
|
|
34718
|
-
const
|
|
34719
|
-
if (!
|
|
34720
|
-
const
|
|
34721
|
-
|
|
34722
|
-
|
|
34723
|
-
const ret = fn.body.body.find((stmt) => t4.isReturnStatement(stmt));
|
|
34724
|
-
if (ret && t4.isReturnStatement(ret) && ret.argument && (t4.isJSXElement(ret.argument) || t4.isJSXFragment(ret.argument))) {
|
|
34725
|
-
return ret.argument;
|
|
34726
|
-
}
|
|
34727
|
-
}
|
|
34728
|
-
return null;
|
|
34729
|
-
};
|
|
34730
|
-
const jsx = getReturnedJsx(cb);
|
|
34731
|
-
if (!jsx) return;
|
|
34732
|
-
if (t4.isJSXFragment(jsx)) {
|
|
34733
|
-
warn({
|
|
34734
|
-
code: "FICT-J002",
|
|
34735
|
-
message: "Missing key prop in list rendering.",
|
|
34736
|
-
fileName,
|
|
34737
|
-
line: expr.loc?.start.line ?? 0,
|
|
34738
|
-
column: expr.loc ? expr.loc.start.column + 1 : 0
|
|
34739
|
-
});
|
|
35597
|
+
const callExprPath = exprPath.get("expression");
|
|
35598
|
+
if (!callExprPath.isCallExpression() && !callExprPath.isOptionalCallExpression()) return;
|
|
35599
|
+
const argPaths = callExprPath.get("arguments");
|
|
35600
|
+
const cbPath = Array.isArray(argPaths) ? argPaths[0] : void 0;
|
|
35601
|
+
if (!cbPath || !cbPath.isArrowFunctionExpression() && !cbPath.isFunctionExpression()) {
|
|
34740
35602
|
return;
|
|
34741
35603
|
}
|
|
34742
|
-
|
|
34743
|
-
|
|
34744
|
-
|
|
34745
|
-
|
|
34746
|
-
|
|
34747
|
-
|
|
35604
|
+
const getReturnedJsx = (fnPath) => {
|
|
35605
|
+
const collectReturnedJsxFromExpression = (node, returned2) => {
|
|
35606
|
+
if (!node) return;
|
|
35607
|
+
if (t4.isJSXElement(node) || t4.isJSXFragment(node)) {
|
|
35608
|
+
returned2.push(node);
|
|
35609
|
+
return;
|
|
35610
|
+
}
|
|
35611
|
+
if (t4.isConditionalExpression(node)) {
|
|
35612
|
+
collectReturnedJsxFromExpression(node.consequent, returned2);
|
|
35613
|
+
collectReturnedJsxFromExpression(node.alternate, returned2);
|
|
35614
|
+
return;
|
|
35615
|
+
}
|
|
35616
|
+
if (t4.isLogicalExpression(node)) {
|
|
35617
|
+
collectReturnedJsxFromExpression(node.left, returned2);
|
|
35618
|
+
collectReturnedJsxFromExpression(node.right, returned2);
|
|
35619
|
+
return;
|
|
35620
|
+
}
|
|
35621
|
+
if (t4.isSequenceExpression(node)) {
|
|
35622
|
+
const tail = node.expressions[node.expressions.length - 1];
|
|
35623
|
+
collectReturnedJsxFromExpression(tail, returned2);
|
|
35624
|
+
return;
|
|
35625
|
+
}
|
|
35626
|
+
if (t4.isParenthesizedExpression(node)) {
|
|
35627
|
+
collectReturnedJsxFromExpression(node.expression, returned2);
|
|
35628
|
+
return;
|
|
35629
|
+
}
|
|
35630
|
+
if (t4.isTSAsExpression(node) || t4.isTSTypeAssertion(node) || t4.isTSNonNullExpression(node) || t4.isTSSatisfiesExpression(node) || t4.isTypeCastExpression(node)) {
|
|
35631
|
+
collectReturnedJsxFromExpression(node.expression, returned2);
|
|
35632
|
+
}
|
|
35633
|
+
};
|
|
35634
|
+
const fn = fnPath.node;
|
|
35635
|
+
const returned = [];
|
|
35636
|
+
if (!t4.isBlockStatement(fn.body)) {
|
|
35637
|
+
collectReturnedJsxFromExpression(fn.body, returned);
|
|
35638
|
+
return returned;
|
|
34748
35639
|
}
|
|
34749
|
-
|
|
34750
|
-
|
|
35640
|
+
fnPath.get("body").traverse({
|
|
35641
|
+
Function(innerFnPath) {
|
|
35642
|
+
innerFnPath.skip();
|
|
35643
|
+
},
|
|
35644
|
+
ReturnStatement(retPath) {
|
|
35645
|
+
collectReturnedJsxFromExpression(retPath.node.argument, returned);
|
|
35646
|
+
}
|
|
35647
|
+
});
|
|
35648
|
+
return returned;
|
|
35649
|
+
};
|
|
35650
|
+
const returnedJsx = getReturnedJsx(cbPath);
|
|
35651
|
+
if (returnedJsx.length === 0) return;
|
|
35652
|
+
const hasMissingKeyBranch = returnedJsx.some((jsx) => {
|
|
35653
|
+
if (t4.isJSXFragment(jsx)) return true;
|
|
35654
|
+
let hasKey = false;
|
|
35655
|
+
for (const attr of jsx.openingElement.attributes) {
|
|
35656
|
+
if (t4.isJSXAttribute(attr) && t4.isJSXIdentifier(attr.name, { name: "key" })) {
|
|
35657
|
+
hasKey = true;
|
|
35658
|
+
break;
|
|
35659
|
+
}
|
|
34751
35660
|
}
|
|
34752
|
-
|
|
34753
|
-
|
|
35661
|
+
return !hasKey;
|
|
35662
|
+
});
|
|
35663
|
+
if (!hasMissingKeyBranch) return;
|
|
34754
35664
|
warn({
|
|
34755
35665
|
code: "FICT-J002",
|
|
34756
35666
|
message: "Missing key prop in list rendering.",
|
|
@@ -35313,8 +36223,10 @@ var createFictPlugin = (0, import_helper_plugin_utils.declare)(
|
|
|
35313
36223
|
var index_default = createFictPlugin;
|
|
35314
36224
|
// Annotate the CommonJS export names for ESM import in node:
|
|
35315
36225
|
0 && (module.exports = {
|
|
36226
|
+
analyzeFictFile,
|
|
35316
36227
|
clearModuleMetadata,
|
|
35317
36228
|
createFictPlugin,
|
|
36229
|
+
inferTraceMarkersForComponent,
|
|
35318
36230
|
resolveModuleMetadata,
|
|
35319
36231
|
setModuleMetadata
|
|
35320
36232
|
});
|