@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.js
CHANGED
|
@@ -3059,7 +3059,7 @@ var require_identifier = __commonJS({
|
|
|
3059
3059
|
value: true
|
|
3060
3060
|
});
|
|
3061
3061
|
exports.isIdentifierChar = isIdentifierChar;
|
|
3062
|
-
exports.isIdentifierName =
|
|
3062
|
+
exports.isIdentifierName = isIdentifierName2;
|
|
3063
3063
|
exports.isIdentifierStart = isIdentifierStart;
|
|
3064
3064
|
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";
|
|
3065
3065
|
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";
|
|
@@ -3100,7 +3100,7 @@ var require_identifier = __commonJS({
|
|
|
3100
3100
|
}
|
|
3101
3101
|
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
|
|
3102
3102
|
}
|
|
3103
|
-
function
|
|
3103
|
+
function isIdentifierName2(name) {
|
|
3104
3104
|
let isFirst = true;
|
|
3105
3105
|
for (let i = 0; i < name.length; i++) {
|
|
3106
3106
|
let cp = name.charCodeAt(i);
|
|
@@ -14159,6 +14159,7 @@ var RUNTIME_HELPERS = {
|
|
|
14159
14159
|
bindEvent: "bindEvent",
|
|
14160
14160
|
callEventHandler: "callEventHandler",
|
|
14161
14161
|
bindRef: "bindRef",
|
|
14162
|
+
spread: "spread",
|
|
14162
14163
|
nonReactive: "nonReactive",
|
|
14163
14164
|
toNodeArray: "toNodeArray",
|
|
14164
14165
|
template: "template",
|
|
@@ -14216,6 +14217,7 @@ var RUNTIME_ALIASES = {
|
|
|
14216
14217
|
bindEvent: "bindEvent",
|
|
14217
14218
|
callEventHandler: "callEventHandler",
|
|
14218
14219
|
bindRef: "bindRef",
|
|
14220
|
+
spread: "spread",
|
|
14219
14221
|
nonReactive: "nonReactive",
|
|
14220
14222
|
toNodeArray: "toNodeArray",
|
|
14221
14223
|
template: "template",
|
|
@@ -17071,6 +17073,37 @@ function clearModuleMetadata(options) {
|
|
|
17071
17073
|
}
|
|
17072
17074
|
|
|
17073
17075
|
// src/validation.ts
|
|
17076
|
+
var DiagnosticCode = /* @__PURE__ */ ((DiagnosticCode2) => {
|
|
17077
|
+
DiagnosticCode2["FICT_P001"] = "FICT-P001";
|
|
17078
|
+
DiagnosticCode2["FICT_P002"] = "FICT-P002";
|
|
17079
|
+
DiagnosticCode2["FICT_P003"] = "FICT-P003";
|
|
17080
|
+
DiagnosticCode2["FICT_P004"] = "FICT-P004";
|
|
17081
|
+
DiagnosticCode2["FICT_P005"] = "FICT-P005";
|
|
17082
|
+
DiagnosticCode2["FICT_S001"] = "FICT-S001";
|
|
17083
|
+
DiagnosticCode2["FICT_S002"] = "FICT-S002";
|
|
17084
|
+
DiagnosticCode2["FICT_E001"] = "FICT-E001";
|
|
17085
|
+
DiagnosticCode2["FICT_E002"] = "FICT-E002";
|
|
17086
|
+
DiagnosticCode2["FICT_E003"] = "FICT-E003";
|
|
17087
|
+
DiagnosticCode2["FICT_M001"] = "FICT-M001";
|
|
17088
|
+
DiagnosticCode2["FICT_M002"] = "FICT-M002";
|
|
17089
|
+
DiagnosticCode2["FICT_M003"] = "FICT-M003";
|
|
17090
|
+
DiagnosticCode2["FICT_C001"] = "FICT-C001";
|
|
17091
|
+
DiagnosticCode2["FICT_C002"] = "FICT-C002";
|
|
17092
|
+
DiagnosticCode2["FICT_C003"] = "FICT-C003";
|
|
17093
|
+
DiagnosticCode2["FICT_C004"] = "FICT-C004";
|
|
17094
|
+
DiagnosticCode2["FICT_J001"] = "FICT-J001";
|
|
17095
|
+
DiagnosticCode2["FICT_J002"] = "FICT-J002";
|
|
17096
|
+
DiagnosticCode2["FICT_J003"] = "FICT-J003";
|
|
17097
|
+
DiagnosticCode2["FICT_R001"] = "FICT-R001";
|
|
17098
|
+
DiagnosticCode2["FICT_R002"] = "FICT-R002";
|
|
17099
|
+
DiagnosticCode2["FICT_R003"] = "FICT-R003";
|
|
17100
|
+
DiagnosticCode2["FICT_R004"] = "FICT-R004";
|
|
17101
|
+
DiagnosticCode2["FICT_R005"] = "FICT-R005";
|
|
17102
|
+
DiagnosticCode2["FICT_X001"] = "FICT-X001";
|
|
17103
|
+
DiagnosticCode2["FICT_X002"] = "FICT-X002";
|
|
17104
|
+
DiagnosticCode2["FICT_X003"] = "FICT-X003";
|
|
17105
|
+
return DiagnosticCode2;
|
|
17106
|
+
})(DiagnosticCode || {});
|
|
17074
17107
|
var DiagnosticMessages = {
|
|
17075
17108
|
["FICT-P001" /* FICT_P001 */]: "Props destructuring falls back to non-reactive binding.",
|
|
17076
17109
|
["FICT-P002" /* FICT_P002 */]: "Array rest in props destructuring falls back to non-reactive binding.",
|
|
@@ -17158,6 +17191,16 @@ function reportDiagnostic(ctx, code, node, context) {
|
|
|
17158
17191
|
});
|
|
17159
17192
|
}
|
|
17160
17193
|
}
|
|
17194
|
+
function getAllDiagnosticCodes() {
|
|
17195
|
+
return Object.values(DiagnosticCode);
|
|
17196
|
+
}
|
|
17197
|
+
function getDiagnosticInfo(code) {
|
|
17198
|
+
return {
|
|
17199
|
+
code,
|
|
17200
|
+
severity: DiagnosticSeverities[code],
|
|
17201
|
+
message: DiagnosticMessages[code]
|
|
17202
|
+
};
|
|
17203
|
+
}
|
|
17161
17204
|
|
|
17162
17205
|
// src/ir/ssa.ts
|
|
17163
17206
|
function enterSSA(program) {
|
|
@@ -22601,138 +22644,212 @@ function emitConditionalChild(startMarkerId, endMarkerId, expr, statements, ctx,
|
|
|
22601
22644
|
);
|
|
22602
22645
|
}
|
|
22603
22646
|
|
|
22604
|
-
// src/ir/
|
|
22605
|
-
function
|
|
22606
|
-
|
|
22607
|
-
|
|
22608
|
-
|
|
22609
|
-
|
|
22610
|
-
|
|
22611
|
-
|
|
22612
|
-
|
|
22613
|
-
|
|
22614
|
-
|
|
22615
|
-
|
|
22616
|
-
|
|
22617
|
-
|
|
22618
|
-
|
|
22619
|
-
|
|
22620
|
-
|
|
22621
|
-
|
|
22622
|
-
|
|
22647
|
+
// src/ir/walk-expression.ts
|
|
22648
|
+
function assertNever(value) {
|
|
22649
|
+
throw new Error(`Unhandled node in walkExpression: ${JSON.stringify(value)}`);
|
|
22650
|
+
}
|
|
22651
|
+
function walkTerminator(term, visitNode, inFunctionBody) {
|
|
22652
|
+
switch (term.kind) {
|
|
22653
|
+
case "Return":
|
|
22654
|
+
if (term.argument) visitNode(term.argument, null, inFunctionBody);
|
|
22655
|
+
return;
|
|
22656
|
+
case "Throw":
|
|
22657
|
+
visitNode(term.argument, null, inFunctionBody);
|
|
22658
|
+
return;
|
|
22659
|
+
case "Branch":
|
|
22660
|
+
visitNode(term.test, null, inFunctionBody);
|
|
22661
|
+
return;
|
|
22662
|
+
case "Switch":
|
|
22663
|
+
visitNode(term.discriminant, null, inFunctionBody);
|
|
22664
|
+
term.cases.forEach((c) => {
|
|
22665
|
+
if (c.test) visitNode(c.test, null, inFunctionBody);
|
|
22666
|
+
});
|
|
22667
|
+
return;
|
|
22668
|
+
case "ForOf":
|
|
22669
|
+
visitNode(term.iterable, null, inFunctionBody);
|
|
22670
|
+
return;
|
|
22671
|
+
case "ForIn":
|
|
22672
|
+
visitNode(term.object, null, inFunctionBody);
|
|
22673
|
+
return;
|
|
22674
|
+
case "Jump":
|
|
22675
|
+
case "Unreachable":
|
|
22676
|
+
case "Break":
|
|
22677
|
+
case "Continue":
|
|
22678
|
+
case "Try":
|
|
22679
|
+
return;
|
|
22680
|
+
default:
|
|
22681
|
+
assertNever(term);
|
|
22682
|
+
}
|
|
22683
|
+
}
|
|
22684
|
+
function walkInstruction(instr, visitNode, inFunctionBody) {
|
|
22685
|
+
switch (instr.kind) {
|
|
22686
|
+
case "Assign":
|
|
22687
|
+
case "Expression":
|
|
22688
|
+
visitNode(instr.value, null, inFunctionBody);
|
|
22689
|
+
return;
|
|
22690
|
+
case "Phi":
|
|
22691
|
+
instr.sources.forEach((source) => visitNode(source.id, null, inFunctionBody));
|
|
22692
|
+
return;
|
|
22693
|
+
default:
|
|
22694
|
+
assertNever(instr);
|
|
22623
22695
|
}
|
|
22624
|
-
return void 0;
|
|
22625
22696
|
}
|
|
22626
|
-
function
|
|
22697
|
+
function walkBlocks(blocks, visitNode, inFunctionBody) {
|
|
22627
22698
|
for (const block of blocks) {
|
|
22628
|
-
|
|
22629
|
-
|
|
22630
|
-
|
|
22631
|
-
|
|
22632
|
-
|
|
22633
|
-
|
|
22634
|
-
|
|
22635
|
-
|
|
22636
|
-
|
|
22699
|
+
block.instructions.forEach((instr) => walkInstruction(instr, visitNode, inFunctionBody));
|
|
22700
|
+
walkTerminator(block.terminator, visitNode, inFunctionBody);
|
|
22701
|
+
}
|
|
22702
|
+
}
|
|
22703
|
+
function walkExpression(expr, visit, options = {}) {
|
|
22704
|
+
const includeFunctionBodies = options.includeFunctionBodies ?? true;
|
|
22705
|
+
const visitNode = (node, parent, inFunctionBody) => {
|
|
22706
|
+
visit(node, { parent, inFunctionBody });
|
|
22707
|
+
switch (node.kind) {
|
|
22708
|
+
case "Identifier":
|
|
22709
|
+
case "Literal":
|
|
22710
|
+
case "MetaProperty":
|
|
22711
|
+
case "ThisExpression":
|
|
22712
|
+
case "SuperExpression":
|
|
22713
|
+
return;
|
|
22714
|
+
case "ImportExpression":
|
|
22715
|
+
visitNode(node.source, node, inFunctionBody);
|
|
22716
|
+
return;
|
|
22717
|
+
case "CallExpression":
|
|
22718
|
+
case "OptionalCallExpression":
|
|
22719
|
+
visitNode(node.callee, node, inFunctionBody);
|
|
22720
|
+
node.arguments.forEach((arg) => visitNode(arg, node, inFunctionBody));
|
|
22721
|
+
return;
|
|
22722
|
+
case "MemberExpression":
|
|
22723
|
+
case "OptionalMemberExpression":
|
|
22724
|
+
visitNode(node.object, node, inFunctionBody);
|
|
22725
|
+
if (node.computed) {
|
|
22726
|
+
visitNode(node.property, node, inFunctionBody);
|
|
22727
|
+
}
|
|
22728
|
+
return;
|
|
22729
|
+
case "BinaryExpression":
|
|
22730
|
+
case "LogicalExpression":
|
|
22731
|
+
visitNode(node.left, node, inFunctionBody);
|
|
22732
|
+
visitNode(node.right, node, inFunctionBody);
|
|
22733
|
+
return;
|
|
22734
|
+
case "UnaryExpression":
|
|
22735
|
+
case "AwaitExpression":
|
|
22736
|
+
visitNode(node.argument, node, inFunctionBody);
|
|
22737
|
+
return;
|
|
22738
|
+
case "ConditionalExpression":
|
|
22739
|
+
visitNode(node.test, node, inFunctionBody);
|
|
22740
|
+
visitNode(node.consequent, node, inFunctionBody);
|
|
22741
|
+
visitNode(node.alternate, node, inFunctionBody);
|
|
22742
|
+
return;
|
|
22743
|
+
case "ArrayExpression":
|
|
22744
|
+
node.elements.forEach((el) => visitNode(el, node, inFunctionBody));
|
|
22745
|
+
return;
|
|
22746
|
+
case "ObjectExpression":
|
|
22747
|
+
node.properties.forEach((prop) => {
|
|
22748
|
+
if (prop.kind === "SpreadElement") {
|
|
22749
|
+
visitNode(prop.argument, node, inFunctionBody);
|
|
22750
|
+
} else {
|
|
22751
|
+
if (prop.computed) {
|
|
22752
|
+
visitNode(prop.key, node, inFunctionBody);
|
|
22753
|
+
}
|
|
22754
|
+
visitNode(prop.value, node, inFunctionBody);
|
|
22637
22755
|
}
|
|
22638
|
-
|
|
22639
|
-
|
|
22640
|
-
|
|
22641
|
-
|
|
22642
|
-
|
|
22643
|
-
const term = block.terminator;
|
|
22644
|
-
switch (term.kind) {
|
|
22645
|
-
case "Return":
|
|
22646
|
-
if (term.argument) collectExpressionDependencies(term.argument, deps);
|
|
22647
|
-
break;
|
|
22648
|
-
case "Throw":
|
|
22649
|
-
collectExpressionDependencies(term.argument, deps);
|
|
22650
|
-
break;
|
|
22651
|
-
case "Branch":
|
|
22652
|
-
collectExpressionDependencies(term.test, deps);
|
|
22653
|
-
break;
|
|
22654
|
-
case "Switch":
|
|
22655
|
-
collectExpressionDependencies(term.discriminant, deps);
|
|
22656
|
-
for (const c of term.cases) {
|
|
22657
|
-
if (c.test) collectExpressionDependencies(c.test, deps);
|
|
22756
|
+
});
|
|
22757
|
+
return;
|
|
22758
|
+
case "JSXElement":
|
|
22759
|
+
if (typeof node.tagName !== "string") {
|
|
22760
|
+
visitNode(node.tagName, node, inFunctionBody);
|
|
22658
22761
|
}
|
|
22659
|
-
|
|
22660
|
-
|
|
22661
|
-
|
|
22662
|
-
|
|
22663
|
-
|
|
22664
|
-
|
|
22665
|
-
|
|
22762
|
+
node.attributes.forEach((attr) => {
|
|
22763
|
+
if (attr.isSpread && attr.spreadExpr) {
|
|
22764
|
+
visitNode(attr.spreadExpr, node, inFunctionBody);
|
|
22765
|
+
} else if (attr.value) {
|
|
22766
|
+
visitNode(attr.value, node, inFunctionBody);
|
|
22767
|
+
}
|
|
22768
|
+
});
|
|
22769
|
+
node.children.forEach((child) => {
|
|
22770
|
+
if (child.kind === "expression") {
|
|
22771
|
+
visitNode(child.value, node, inFunctionBody);
|
|
22772
|
+
} else if (child.kind === "element") {
|
|
22773
|
+
visitNode(child.value, node, inFunctionBody);
|
|
22774
|
+
}
|
|
22775
|
+
});
|
|
22776
|
+
return;
|
|
22777
|
+
case "ArrowFunction":
|
|
22778
|
+
if (!includeFunctionBodies) return;
|
|
22779
|
+
if (node.isExpression && !Array.isArray(node.body)) {
|
|
22780
|
+
visitNode(node.body, node, true);
|
|
22781
|
+
} else if (Array.isArray(node.body)) {
|
|
22782
|
+
walkBlocks(node.body, visitNode, true);
|
|
22783
|
+
}
|
|
22784
|
+
return;
|
|
22785
|
+
case "FunctionExpression":
|
|
22786
|
+
if (!includeFunctionBodies) return;
|
|
22787
|
+
walkBlocks(node.body, visitNode, true);
|
|
22788
|
+
return;
|
|
22789
|
+
case "AssignmentExpression":
|
|
22790
|
+
visitNode(node.left, node, inFunctionBody);
|
|
22791
|
+
visitNode(node.right, node, inFunctionBody);
|
|
22792
|
+
return;
|
|
22793
|
+
case "UpdateExpression":
|
|
22794
|
+
visitNode(node.argument, node, inFunctionBody);
|
|
22795
|
+
return;
|
|
22796
|
+
case "TemplateLiteral":
|
|
22797
|
+
node.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
|
|
22798
|
+
return;
|
|
22799
|
+
case "SpreadElement":
|
|
22800
|
+
visitNode(node.argument, node, inFunctionBody);
|
|
22801
|
+
return;
|
|
22802
|
+
case "NewExpression":
|
|
22803
|
+
visitNode(node.callee, node, inFunctionBody);
|
|
22804
|
+
node.arguments.forEach((arg) => visitNode(arg, node, inFunctionBody));
|
|
22805
|
+
return;
|
|
22806
|
+
case "SequenceExpression":
|
|
22807
|
+
node.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
|
|
22808
|
+
return;
|
|
22809
|
+
case "YieldExpression":
|
|
22810
|
+
if (node.argument) {
|
|
22811
|
+
visitNode(node.argument, node, inFunctionBody);
|
|
22812
|
+
}
|
|
22813
|
+
return;
|
|
22814
|
+
case "TaggedTemplateExpression":
|
|
22815
|
+
visitNode(node.tag, node, inFunctionBody);
|
|
22816
|
+
node.quasi.expressions.forEach((item) => visitNode(item, node, inFunctionBody));
|
|
22817
|
+
return;
|
|
22818
|
+
case "ClassExpression":
|
|
22819
|
+
if (node.superClass) {
|
|
22820
|
+
visitNode(node.superClass, node, inFunctionBody);
|
|
22821
|
+
}
|
|
22822
|
+
return;
|
|
22666
22823
|
default:
|
|
22667
|
-
|
|
22824
|
+
assertNever(node);
|
|
22668
22825
|
}
|
|
22826
|
+
};
|
|
22827
|
+
visitNode(expr, null, false);
|
|
22828
|
+
}
|
|
22829
|
+
|
|
22830
|
+
// src/ir/codegen-expression-deps.ts
|
|
22831
|
+
function getMemberDependencyPath(expr) {
|
|
22832
|
+
if (expr.kind !== "MemberExpression" && expr.kind !== "OptionalMemberExpression") return void 0;
|
|
22833
|
+
const depPath = extractDependencyPath(expr);
|
|
22834
|
+
if (!depPath || depPath.segments.length === 0) return void 0;
|
|
22835
|
+
const base = deSSAVarName(depPath.base);
|
|
22836
|
+
if (depPath.segments.some((segment) => segment.computed)) {
|
|
22837
|
+
return base;
|
|
22669
22838
|
}
|
|
22839
|
+
const tail = depPath.segments.map((segment) => segment.property).join(".");
|
|
22840
|
+
return tail ? `${base}.${tail}` : void 0;
|
|
22670
22841
|
}
|
|
22671
22842
|
function collectExpressionDependencies(expr, deps) {
|
|
22672
|
-
|
|
22673
|
-
|
|
22674
|
-
|
|
22675
|
-
|
|
22676
|
-
if (expr.kind === "ArrowFunction") {
|
|
22677
|
-
if (expr.isExpression && !Array.isArray(expr.body)) {
|
|
22678
|
-
collectExpressionDependencies(expr.body, deps);
|
|
22679
|
-
} else if (Array.isArray(expr.body)) {
|
|
22680
|
-
collectBlockDependencies(expr.body, deps);
|
|
22843
|
+
walkExpression(expr, (node) => {
|
|
22844
|
+
if (node.kind === "Identifier") {
|
|
22845
|
+
deps.add(deSSAVarName(node.name));
|
|
22846
|
+
return;
|
|
22681
22847
|
}
|
|
22682
|
-
|
|
22683
|
-
|
|
22684
|
-
|
|
22685
|
-
collectBlockDependencies(expr.body, deps);
|
|
22686
|
-
return;
|
|
22687
|
-
}
|
|
22688
|
-
if (expr.kind === "MemberExpression") {
|
|
22689
|
-
const path2 = getMemberDependencyPath(expr);
|
|
22690
|
-
if (path2) deps.add(path2);
|
|
22691
|
-
collectExpressionDependencies(expr.object, deps);
|
|
22692
|
-
if (expr.computed && expr.property.kind !== "Literal") {
|
|
22693
|
-
collectExpressionDependencies(expr.property, deps);
|
|
22848
|
+
const path2 = getMemberDependencyPath(node);
|
|
22849
|
+
if (path2) {
|
|
22850
|
+
deps.add(path2);
|
|
22694
22851
|
}
|
|
22695
|
-
|
|
22696
|
-
}
|
|
22697
|
-
if (expr.kind === "CallExpression") {
|
|
22698
|
-
collectExpressionDependencies(expr.callee, deps);
|
|
22699
|
-
expr.arguments.forEach((a) => collectExpressionDependencies(a, deps));
|
|
22700
|
-
return;
|
|
22701
|
-
}
|
|
22702
|
-
if (expr.kind === "BinaryExpression" || expr.kind === "LogicalExpression") {
|
|
22703
|
-
collectExpressionDependencies(expr.left, deps);
|
|
22704
|
-
collectExpressionDependencies(expr.right, deps);
|
|
22705
|
-
return;
|
|
22706
|
-
}
|
|
22707
|
-
if (expr.kind === "ConditionalExpression") {
|
|
22708
|
-
collectExpressionDependencies(expr.test, deps);
|
|
22709
|
-
collectExpressionDependencies(expr.consequent, deps);
|
|
22710
|
-
collectExpressionDependencies(expr.alternate, deps);
|
|
22711
|
-
return;
|
|
22712
|
-
}
|
|
22713
|
-
if (expr.kind === "UnaryExpression") {
|
|
22714
|
-
collectExpressionDependencies(expr.argument, deps);
|
|
22715
|
-
return;
|
|
22716
|
-
}
|
|
22717
|
-
if (expr.kind === "ArrayExpression") {
|
|
22718
|
-
expr.elements.forEach((el) => collectExpressionDependencies(el, deps));
|
|
22719
|
-
return;
|
|
22720
|
-
}
|
|
22721
|
-
if (expr.kind === "ObjectExpression") {
|
|
22722
|
-
expr.properties.forEach((p) => {
|
|
22723
|
-
if (p.kind === "SpreadElement") {
|
|
22724
|
-
collectExpressionDependencies(p.argument, deps);
|
|
22725
|
-
} else {
|
|
22726
|
-
if (p.computed) collectExpressionDependencies(p.key, deps);
|
|
22727
|
-
collectExpressionDependencies(p.value, deps);
|
|
22728
|
-
}
|
|
22729
|
-
});
|
|
22730
|
-
return;
|
|
22731
|
-
}
|
|
22732
|
-
if (expr.kind === "TemplateLiteral") {
|
|
22733
|
-
expr.expressions.forEach((e) => collectExpressionDependencies(e, deps));
|
|
22734
|
-
return;
|
|
22735
|
-
}
|
|
22852
|
+
});
|
|
22736
22853
|
}
|
|
22737
22854
|
|
|
22738
22855
|
// src/ir/codegen-reactive-kind.ts
|
|
@@ -24176,34 +24293,138 @@ function extractKeyFromAttributes(attributes) {
|
|
|
24176
24293
|
}
|
|
24177
24294
|
return void 0;
|
|
24178
24295
|
}
|
|
24296
|
+
function collectReturnedJSXFromExpression(expression, returned) {
|
|
24297
|
+
if (expression.kind === "JSXElement") {
|
|
24298
|
+
returned.push(expression);
|
|
24299
|
+
return;
|
|
24300
|
+
}
|
|
24301
|
+
if (expression.kind === "ConditionalExpression") {
|
|
24302
|
+
collectReturnedJSXFromExpression(expression.consequent, returned);
|
|
24303
|
+
collectReturnedJSXFromExpression(expression.alternate, returned);
|
|
24304
|
+
return;
|
|
24305
|
+
}
|
|
24306
|
+
if (expression.kind === "LogicalExpression") {
|
|
24307
|
+
collectReturnedJSXFromExpression(expression.left, returned);
|
|
24308
|
+
collectReturnedJSXFromExpression(expression.right, returned);
|
|
24309
|
+
return;
|
|
24310
|
+
}
|
|
24311
|
+
if (expression.kind === "SequenceExpression") {
|
|
24312
|
+
const tail = expression.expressions[expression.expressions.length - 1];
|
|
24313
|
+
if (tail) collectReturnedJSXFromExpression(tail, returned);
|
|
24314
|
+
}
|
|
24315
|
+
}
|
|
24316
|
+
function extractKeyExpressionFromReturnedExpression(expression) {
|
|
24317
|
+
if (expression.kind === "JSXElement") {
|
|
24318
|
+
return extractKeyFromAttributes(expression.attributes);
|
|
24319
|
+
}
|
|
24320
|
+
if (expression.kind === "ConditionalExpression") {
|
|
24321
|
+
const consequentKey = extractKeyExpressionFromReturnedExpression(expression.consequent);
|
|
24322
|
+
const alternateKey = extractKeyExpressionFromReturnedExpression(expression.alternate);
|
|
24323
|
+
if (!consequentKey || !alternateKey) return void 0;
|
|
24324
|
+
return {
|
|
24325
|
+
kind: "ConditionalExpression",
|
|
24326
|
+
test: expression.test,
|
|
24327
|
+
consequent: consequentKey,
|
|
24328
|
+
alternate: alternateKey,
|
|
24329
|
+
loc: expression.loc
|
|
24330
|
+
};
|
|
24331
|
+
}
|
|
24332
|
+
if (expression.kind === "SequenceExpression") {
|
|
24333
|
+
const tail = expression.expressions[expression.expressions.length - 1];
|
|
24334
|
+
return tail ? extractKeyExpressionFromReturnedExpression(tail) : void 0;
|
|
24335
|
+
}
|
|
24336
|
+
return void 0;
|
|
24337
|
+
}
|
|
24338
|
+
function getReturnedKeyExpressionsFromCallback(callback) {
|
|
24339
|
+
const returned = [];
|
|
24340
|
+
if (callback.kind === "ArrowFunction") {
|
|
24341
|
+
if (callback.isExpression && !Array.isArray(callback.body)) {
|
|
24342
|
+
const keyExpr = extractKeyExpressionFromReturnedExpression(callback.body);
|
|
24343
|
+
if (keyExpr) returned.push(keyExpr);
|
|
24344
|
+
return returned;
|
|
24345
|
+
}
|
|
24346
|
+
if (Array.isArray(callback.body)) {
|
|
24347
|
+
for (const block of callback.body) {
|
|
24348
|
+
const term = block.terminator;
|
|
24349
|
+
if (term.kind !== "Return" || !term.argument) continue;
|
|
24350
|
+
const keyExpr = extractKeyExpressionFromReturnedExpression(term.argument);
|
|
24351
|
+
if (keyExpr) returned.push(keyExpr);
|
|
24352
|
+
}
|
|
24353
|
+
}
|
|
24354
|
+
return returned;
|
|
24355
|
+
}
|
|
24356
|
+
if (callback.kind === "FunctionExpression") {
|
|
24357
|
+
for (const block of callback.body ?? []) {
|
|
24358
|
+
const term = block.terminator;
|
|
24359
|
+
if (term.kind !== "Return" || !term.argument) continue;
|
|
24360
|
+
const keyExpr = extractKeyExpressionFromReturnedExpression(term.argument);
|
|
24361
|
+
if (keyExpr) returned.push(keyExpr);
|
|
24362
|
+
}
|
|
24363
|
+
}
|
|
24364
|
+
return returned;
|
|
24365
|
+
}
|
|
24179
24366
|
function getReturnedJSXFromCallback(callback) {
|
|
24367
|
+
const returned = [];
|
|
24180
24368
|
if (callback.kind === "ArrowFunction") {
|
|
24181
|
-
if (callback.isExpression && !Array.isArray(callback.body)
|
|
24182
|
-
|
|
24369
|
+
if (callback.isExpression && !Array.isArray(callback.body)) {
|
|
24370
|
+
collectReturnedJSXFromExpression(callback.body, returned);
|
|
24371
|
+
return returned;
|
|
24183
24372
|
}
|
|
24184
24373
|
if (Array.isArray(callback.body)) {
|
|
24185
24374
|
for (const block of callback.body) {
|
|
24186
24375
|
const term = block.terminator;
|
|
24187
|
-
if (term.kind === "Return" && term.argument
|
|
24188
|
-
|
|
24376
|
+
if (term.kind === "Return" && term.argument) {
|
|
24377
|
+
collectReturnedJSXFromExpression(term.argument, returned);
|
|
24189
24378
|
}
|
|
24190
24379
|
}
|
|
24191
24380
|
}
|
|
24381
|
+
return returned;
|
|
24192
24382
|
}
|
|
24193
24383
|
if (callback.kind === "FunctionExpression") {
|
|
24194
24384
|
for (const block of callback.body ?? []) {
|
|
24195
24385
|
const term = block.terminator;
|
|
24196
|
-
if (term.kind === "Return" && term.argument
|
|
24197
|
-
|
|
24386
|
+
if (term.kind === "Return" && term.argument) {
|
|
24387
|
+
collectReturnedJSXFromExpression(term.argument, returned);
|
|
24198
24388
|
}
|
|
24199
24389
|
}
|
|
24200
24390
|
}
|
|
24201
|
-
return
|
|
24391
|
+
return returned;
|
|
24392
|
+
}
|
|
24393
|
+
function keyExpressionSignature(expression) {
|
|
24394
|
+
try {
|
|
24395
|
+
return JSON.stringify(expression, (key, value) => {
|
|
24396
|
+
if (key === "loc") return void 0;
|
|
24397
|
+
if (typeof value === "bigint") return `__bigint:${value.toString()}`;
|
|
24398
|
+
return value;
|
|
24399
|
+
}) ?? "";
|
|
24400
|
+
} catch {
|
|
24401
|
+
return "";
|
|
24402
|
+
}
|
|
24202
24403
|
}
|
|
24203
24404
|
function extractKeyFromMapCallback(callback) {
|
|
24204
|
-
const
|
|
24205
|
-
if (
|
|
24206
|
-
|
|
24405
|
+
const returnedKeyExpressions = getReturnedKeyExpressionsFromCallback(callback);
|
|
24406
|
+
if (returnedKeyExpressions.length === 1) {
|
|
24407
|
+
return returnedKeyExpressions[0];
|
|
24408
|
+
}
|
|
24409
|
+
if (returnedKeyExpressions.length > 1) {
|
|
24410
|
+
const [firstKey2, ...restKeys2] = returnedKeyExpressions;
|
|
24411
|
+
const firstSignature2 = keyExpressionSignature(firstKey2);
|
|
24412
|
+
if (firstSignature2 && restKeys2.every((keyExpr) => keyExpressionSignature(keyExpr) === firstSignature2)) {
|
|
24413
|
+
return firstKey2;
|
|
24414
|
+
}
|
|
24415
|
+
}
|
|
24416
|
+
const returned = getReturnedJSXFromCallback(callback);
|
|
24417
|
+
if (returned.length === 0) return void 0;
|
|
24418
|
+
const keyExpressions = returned.map((jsx) => extractKeyFromAttributes(jsx.attributes));
|
|
24419
|
+
if (keyExpressions.some((expr) => !expr)) return void 0;
|
|
24420
|
+
const [firstKey, ...restKeys] = keyExpressions;
|
|
24421
|
+
const firstSignature = keyExpressionSignature(firstKey);
|
|
24422
|
+
if (!firstSignature) return void 0;
|
|
24423
|
+
const allBranchesSameKey = restKeys.every(
|
|
24424
|
+
(keyExpr) => keyExpressionSignature(keyExpr) === firstSignature
|
|
24425
|
+
);
|
|
24426
|
+
if (!allBranchesSameKey) return void 0;
|
|
24427
|
+
return firstKey;
|
|
24207
24428
|
}
|
|
24208
24429
|
|
|
24209
24430
|
// src/ir/codegen-overrides.ts
|
|
@@ -24808,6 +25029,15 @@ function buildListCallExpression(expr, statements, ctx, ops) {
|
|
|
24808
25029
|
ctx.inListRender = true;
|
|
24809
25030
|
let callbackExpr = ops.lowerExpression(mapCallback, ctx);
|
|
24810
25031
|
ctx.inListRender = prevInListRender;
|
|
25032
|
+
const shouldDeferOptionalCallbackEvaluation = isOptional && !t4.isArrowFunctionExpression(callbackExpr) && !t4.isFunctionExpression(callbackExpr);
|
|
25033
|
+
let deferredCallbackId = null;
|
|
25034
|
+
let deferredCallbackInitId = null;
|
|
25035
|
+
let deferredItemsId = null;
|
|
25036
|
+
if (shouldDeferOptionalCallbackEvaluation) {
|
|
25037
|
+
deferredCallbackId = ops.genTemp(ctx, "mapCb");
|
|
25038
|
+
deferredCallbackInitId = ops.genTemp(ctx, "mapCbReady");
|
|
25039
|
+
deferredItemsId = ops.genTemp(ctx, "mapItems");
|
|
25040
|
+
}
|
|
24811
25041
|
const capturedKeyParamName = ctx.listKeyParamName;
|
|
24812
25042
|
ctx.listKeyExpr = prevListKeyExpr;
|
|
24813
25043
|
ctx.listItemParamName = prevListItemParamName;
|
|
@@ -24907,7 +25137,7 @@ function buildListCallExpression(expr, statements, ctx, ops) {
|
|
|
24907
25137
|
],
|
|
24908
25138
|
keyExprAst
|
|
24909
25139
|
);
|
|
24910
|
-
const hasIndexParam = (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
25140
|
+
const hasIndexParam = shouldDeferOptionalCallbackEvaluation || (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
24911
25141
|
if (canConstifyKey && (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr))) {
|
|
24912
25142
|
const newParams = [...callbackExpr.params];
|
|
24913
25143
|
while (newParams.length < 2) {
|
|
@@ -24927,25 +25157,131 @@ function buildListCallExpression(expr, statements, ctx, ops) {
|
|
|
24927
25157
|
}
|
|
24928
25158
|
}
|
|
24929
25159
|
statements.push(...hoistedStatements);
|
|
25160
|
+
if (shouldDeferOptionalCallbackEvaluation) {
|
|
25161
|
+
statements.push(
|
|
25162
|
+
t4.variableDeclaration("let", [
|
|
25163
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackId, true))
|
|
25164
|
+
]),
|
|
25165
|
+
t4.variableDeclaration("let", [
|
|
25166
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackInitId, true), t4.booleanLiteral(false))
|
|
25167
|
+
])
|
|
25168
|
+
);
|
|
25169
|
+
}
|
|
25170
|
+
const getItemsExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25171
|
+
[],
|
|
25172
|
+
t4.blockStatement([
|
|
25173
|
+
t4.variableDeclaration("const", [
|
|
25174
|
+
t4.variableDeclarator(
|
|
25175
|
+
t4.cloneNode(deferredItemsId, true),
|
|
25176
|
+
t4.cloneNode(arrayExprBase, true)
|
|
25177
|
+
)
|
|
25178
|
+
]),
|
|
25179
|
+
t4.ifStatement(
|
|
25180
|
+
t4.binaryExpression("==", t4.cloneNode(deferredItemsId, true), t4.nullLiteral()),
|
|
25181
|
+
t4.blockStatement([t4.returnStatement(t4.arrayExpression([]))])
|
|
25182
|
+
),
|
|
25183
|
+
t4.ifStatement(
|
|
25184
|
+
t4.unaryExpression("!", t4.cloneNode(deferredCallbackInitId, true)),
|
|
25185
|
+
t4.blockStatement([
|
|
25186
|
+
t4.expressionStatement(
|
|
25187
|
+
t4.assignmentExpression(
|
|
25188
|
+
"=",
|
|
25189
|
+
t4.cloneNode(deferredCallbackId, true),
|
|
25190
|
+
t4.cloneNode(callbackExpr, true)
|
|
25191
|
+
)
|
|
25192
|
+
),
|
|
25193
|
+
t4.expressionStatement(
|
|
25194
|
+
t4.assignmentExpression(
|
|
25195
|
+
"=",
|
|
25196
|
+
t4.cloneNode(deferredCallbackInitId, true),
|
|
25197
|
+
t4.booleanLiteral(true)
|
|
25198
|
+
)
|
|
25199
|
+
)
|
|
25200
|
+
])
|
|
25201
|
+
),
|
|
25202
|
+
t4.returnStatement(t4.cloneNode(deferredItemsId, true))
|
|
25203
|
+
])
|
|
25204
|
+
) : t4.arrowFunctionExpression([], arrayExpr);
|
|
25205
|
+
const renderExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25206
|
+
[t4.identifier("__item"), t4.identifier("__index"), t4.identifier("__key")],
|
|
25207
|
+
t4.callExpression(t4.cloneNode(deferredCallbackId, true), [
|
|
25208
|
+
t4.identifier("__item"),
|
|
25209
|
+
t4.identifier("__index"),
|
|
25210
|
+
t4.identifier("__key")
|
|
25211
|
+
])
|
|
25212
|
+
) : callbackExpr;
|
|
24930
25213
|
listCall = t4.callExpression(t4.identifier(RUNTIME_ALIASES.keyedList), [
|
|
24931
|
-
|
|
25214
|
+
getItemsExpr,
|
|
24932
25215
|
keyFn,
|
|
24933
|
-
|
|
25216
|
+
renderExpr,
|
|
24934
25217
|
t4.booleanLiteral(hasIndexParam)
|
|
24935
25218
|
]);
|
|
24936
25219
|
} else {
|
|
24937
25220
|
statements.push(...hoistedStatements);
|
|
25221
|
+
if (shouldDeferOptionalCallbackEvaluation) {
|
|
25222
|
+
statements.push(
|
|
25223
|
+
t4.variableDeclaration("let", [
|
|
25224
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackId, true))
|
|
25225
|
+
]),
|
|
25226
|
+
t4.variableDeclaration("let", [
|
|
25227
|
+
t4.variableDeclarator(t4.cloneNode(deferredCallbackInitId, true), t4.booleanLiteral(false))
|
|
25228
|
+
])
|
|
25229
|
+
);
|
|
25230
|
+
}
|
|
24938
25231
|
const itemParamName = t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr) ? t4.isIdentifier(callbackExpr.params[0]) ? callbackExpr.params[0].name : "__item" : "__item";
|
|
24939
25232
|
const indexParamName = t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr) ? t4.isIdentifier(callbackExpr.params[1]) ? callbackExpr.params[1].name : "__index" : "__index";
|
|
24940
|
-
const hasIndexParam = (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
25233
|
+
const hasIndexParam = shouldDeferOptionalCallbackEvaluation || (t4.isArrowFunctionExpression(callbackExpr) || t4.isFunctionExpression(callbackExpr)) && callbackExpr.params.length >= 2;
|
|
25234
|
+
const getItemsExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25235
|
+
[],
|
|
25236
|
+
t4.blockStatement([
|
|
25237
|
+
t4.variableDeclaration("const", [
|
|
25238
|
+
t4.variableDeclarator(
|
|
25239
|
+
t4.cloneNode(deferredItemsId, true),
|
|
25240
|
+
t4.cloneNode(arrayExprBase, true)
|
|
25241
|
+
)
|
|
25242
|
+
]),
|
|
25243
|
+
t4.ifStatement(
|
|
25244
|
+
t4.binaryExpression("==", t4.cloneNode(deferredItemsId, true), t4.nullLiteral()),
|
|
25245
|
+
t4.blockStatement([t4.returnStatement(t4.arrayExpression([]))])
|
|
25246
|
+
),
|
|
25247
|
+
t4.ifStatement(
|
|
25248
|
+
t4.unaryExpression("!", t4.cloneNode(deferredCallbackInitId, true)),
|
|
25249
|
+
t4.blockStatement([
|
|
25250
|
+
t4.expressionStatement(
|
|
25251
|
+
t4.assignmentExpression(
|
|
25252
|
+
"=",
|
|
25253
|
+
t4.cloneNode(deferredCallbackId, true),
|
|
25254
|
+
t4.cloneNode(callbackExpr, true)
|
|
25255
|
+
)
|
|
25256
|
+
),
|
|
25257
|
+
t4.expressionStatement(
|
|
25258
|
+
t4.assignmentExpression(
|
|
25259
|
+
"=",
|
|
25260
|
+
t4.cloneNode(deferredCallbackInitId, true),
|
|
25261
|
+
t4.booleanLiteral(true)
|
|
25262
|
+
)
|
|
25263
|
+
)
|
|
25264
|
+
])
|
|
25265
|
+
),
|
|
25266
|
+
t4.returnStatement(t4.cloneNode(deferredItemsId, true))
|
|
25267
|
+
])
|
|
25268
|
+
) : t4.arrowFunctionExpression([], arrayExpr);
|
|
25269
|
+
const renderExpr = shouldDeferOptionalCallbackEvaluation ? t4.arrowFunctionExpression(
|
|
25270
|
+
[t4.identifier("__item"), t4.identifier("__index"), t4.identifier("__key")],
|
|
25271
|
+
t4.callExpression(t4.cloneNode(deferredCallbackId, true), [
|
|
25272
|
+
t4.identifier("__item"),
|
|
25273
|
+
t4.identifier("__index"),
|
|
25274
|
+
t4.identifier("__key")
|
|
25275
|
+
])
|
|
25276
|
+
) : callbackExpr;
|
|
24941
25277
|
const keyFn = t4.arrowFunctionExpression(
|
|
24942
25278
|
[t4.identifier(itemParamName), t4.identifier(indexParamName)],
|
|
24943
25279
|
t4.identifier(indexParamName)
|
|
24944
25280
|
);
|
|
24945
25281
|
listCall = t4.callExpression(t4.identifier(RUNTIME_ALIASES.keyedList), [
|
|
24946
|
-
|
|
25282
|
+
getItemsExpr,
|
|
24947
25283
|
keyFn,
|
|
24948
|
-
|
|
25284
|
+
renderExpr,
|
|
24949
25285
|
t4.booleanLiteral(hasIndexParam)
|
|
24950
25286
|
]);
|
|
24951
25287
|
}
|
|
@@ -26110,8 +26446,31 @@ function extractHIRStaticHtml(jsx, ctx, ops, parentPath = [], namespace = null)
|
|
|
26110
26446
|
const resolvedNamespace = resolveNamespaceContext(tagName, namespace);
|
|
26111
26447
|
let html = `<${tagName}`;
|
|
26112
26448
|
const bindings = [];
|
|
26113
|
-
for (
|
|
26449
|
+
for (let attrIndex = 0; attrIndex < jsx.attributes.length; attrIndex++) {
|
|
26450
|
+
const attr = jsx.attributes[attrIndex];
|
|
26114
26451
|
if (attr.isSpread) {
|
|
26452
|
+
if (attr.spreadExpr) {
|
|
26453
|
+
const excluded = /* @__PURE__ */ new Set();
|
|
26454
|
+
for (let nextIndex = attrIndex + 1; nextIndex < jsx.attributes.length; nextIndex++) {
|
|
26455
|
+
const nextAttr = jsx.attributes[nextIndex];
|
|
26456
|
+
if (nextAttr.isSpread) continue;
|
|
26457
|
+
let nextName = normalizeHIRAttrName(nextAttr.name);
|
|
26458
|
+
if (nextName.endsWith("$")) {
|
|
26459
|
+
nextName = nextName.slice(0, -1);
|
|
26460
|
+
}
|
|
26461
|
+
if (nextName === "key") continue;
|
|
26462
|
+
excluded.add(nextName);
|
|
26463
|
+
if (nextName !== nextAttr.name) {
|
|
26464
|
+
excluded.add(nextAttr.name);
|
|
26465
|
+
}
|
|
26466
|
+
}
|
|
26467
|
+
bindings.push({
|
|
26468
|
+
type: "spread",
|
|
26469
|
+
path: [...parentPath],
|
|
26470
|
+
expr: attr.spreadExpr,
|
|
26471
|
+
exclude: excluded.size > 0 ? Array.from(excluded) : void 0
|
|
26472
|
+
});
|
|
26473
|
+
}
|
|
26115
26474
|
continue;
|
|
26116
26475
|
}
|
|
26117
26476
|
let name = normalizeHIRAttrName(attr.name);
|
|
@@ -28296,10 +28655,28 @@ function lowerIntrinsicElement(jsx, ctx) {
|
|
|
28296
28655
|
)
|
|
28297
28656
|
);
|
|
28298
28657
|
}
|
|
28658
|
+
fusedPatchGroups.clear();
|
|
28299
28659
|
};
|
|
28300
28660
|
for (const binding of bindings) {
|
|
28301
28661
|
const targetId = resolveHIRBindingPath(binding.path, nodeCache, statements, ctx, genTemp3);
|
|
28302
|
-
if (binding.type === "
|
|
28662
|
+
if (binding.type === "spread" && binding.expr) {
|
|
28663
|
+
flushFusedPatchGroups();
|
|
28664
|
+
ctx.helpersUsed.add("spread");
|
|
28665
|
+
const spreadValueExpr = lowerDomExpression(binding.expr, ctx, containingRegion);
|
|
28666
|
+
const spreadGetter = t4.arrowFunctionExpression([], spreadValueExpr);
|
|
28667
|
+
const spreadArgs = [
|
|
28668
|
+
targetId,
|
|
28669
|
+
spreadGetter,
|
|
28670
|
+
t4.booleanLiteral(Boolean(isSVG || isMathML)),
|
|
28671
|
+
t4.booleanLiteral(true)
|
|
28672
|
+
];
|
|
28673
|
+
if (binding.exclude && binding.exclude.length > 0) {
|
|
28674
|
+
spreadArgs.push(t4.arrayExpression(binding.exclude.map((name) => t4.stringLiteral(name))));
|
|
28675
|
+
}
|
|
28676
|
+
statements.push(
|
|
28677
|
+
t4.expressionStatement(t4.callExpression(t4.identifier(RUNTIME_ALIASES.spread), spreadArgs))
|
|
28678
|
+
);
|
|
28679
|
+
} else if (binding.type === "event" && binding.expr && binding.name) {
|
|
28303
28680
|
const eventName = binding.name;
|
|
28304
28681
|
const hasEventOptions = binding.eventOptions && (binding.eventOptions.capture || binding.eventOptions.passive || binding.eventOptions.once);
|
|
28305
28682
|
const isDelegated = DelegatedEvents.has(eventName) && !hasEventOptions;
|
|
@@ -33087,106 +33464,106 @@ function collectUsesFromTerminator(term, add, inFunctionBody = false) {
|
|
|
33087
33464
|
}
|
|
33088
33465
|
}
|
|
33089
33466
|
function collectUsesFromExpression(expr, add, inFunctionBody = false) {
|
|
33090
|
-
|
|
33467
|
+
walkExpression2(expr, add, { inFunctionBody, shadowed: /* @__PURE__ */ new Set() });
|
|
33091
33468
|
}
|
|
33092
|
-
function
|
|
33469
|
+
function walkExpression2(expr, add, ctx) {
|
|
33093
33470
|
switch (expr.kind) {
|
|
33094
33471
|
case "Identifier":
|
|
33095
33472
|
if (!ctx.shadowed.has(expr.name)) add(expr.name, ctx.inFunctionBody);
|
|
33096
33473
|
return;
|
|
33097
33474
|
case "CallExpression":
|
|
33098
33475
|
case "OptionalCallExpression":
|
|
33099
|
-
|
|
33100
|
-
expr.arguments.forEach((arg) =>
|
|
33476
|
+
walkExpression2(expr.callee, add, ctx);
|
|
33477
|
+
expr.arguments.forEach((arg) => walkExpression2(arg, add, ctx));
|
|
33101
33478
|
return;
|
|
33102
33479
|
case "MemberExpression":
|
|
33103
33480
|
case "OptionalMemberExpression":
|
|
33104
|
-
|
|
33105
|
-
if (expr.computed)
|
|
33481
|
+
walkExpression2(expr.object, add, ctx);
|
|
33482
|
+
if (expr.computed) walkExpression2(expr.property, add, ctx);
|
|
33106
33483
|
return;
|
|
33107
33484
|
case "BinaryExpression":
|
|
33108
33485
|
case "LogicalExpression":
|
|
33109
|
-
|
|
33110
|
-
|
|
33486
|
+
walkExpression2(expr.left, add, ctx);
|
|
33487
|
+
walkExpression2(expr.right, add, ctx);
|
|
33111
33488
|
return;
|
|
33112
33489
|
case "UnaryExpression":
|
|
33113
|
-
|
|
33490
|
+
walkExpression2(expr.argument, add, ctx);
|
|
33114
33491
|
return;
|
|
33115
33492
|
case "ConditionalExpression":
|
|
33116
|
-
|
|
33117
|
-
|
|
33118
|
-
|
|
33493
|
+
walkExpression2(expr.test, add, ctx);
|
|
33494
|
+
walkExpression2(expr.consequent, add, ctx);
|
|
33495
|
+
walkExpression2(expr.alternate, add, ctx);
|
|
33119
33496
|
return;
|
|
33120
33497
|
case "ArrayExpression":
|
|
33121
33498
|
expr.elements.forEach((el) => {
|
|
33122
|
-
if (el)
|
|
33499
|
+
if (el) walkExpression2(el, add, ctx);
|
|
33123
33500
|
});
|
|
33124
33501
|
return;
|
|
33125
33502
|
case "ObjectExpression":
|
|
33126
33503
|
expr.properties.forEach((prop) => {
|
|
33127
33504
|
if (prop.kind === "SpreadElement") {
|
|
33128
|
-
|
|
33505
|
+
walkExpression2(prop.argument, add, ctx);
|
|
33129
33506
|
} else {
|
|
33130
|
-
if (prop.computed)
|
|
33131
|
-
|
|
33507
|
+
if (prop.computed) walkExpression2(prop.key, add, ctx);
|
|
33508
|
+
walkExpression2(prop.value, add, ctx);
|
|
33132
33509
|
}
|
|
33133
33510
|
});
|
|
33134
33511
|
return;
|
|
33135
33512
|
case "TemplateLiteral":
|
|
33136
|
-
expr.expressions.forEach((e) =>
|
|
33513
|
+
expr.expressions.forEach((e) => walkExpression2(e, add, ctx));
|
|
33137
33514
|
return;
|
|
33138
33515
|
case "SpreadElement":
|
|
33139
|
-
|
|
33516
|
+
walkExpression2(expr.argument, add, ctx);
|
|
33140
33517
|
return;
|
|
33141
33518
|
case "SequenceExpression":
|
|
33142
|
-
expr.expressions.forEach((e) =>
|
|
33519
|
+
expr.expressions.forEach((e) => walkExpression2(e, add, ctx));
|
|
33143
33520
|
return;
|
|
33144
33521
|
case "AwaitExpression":
|
|
33145
|
-
|
|
33522
|
+
walkExpression2(expr.argument, add, ctx);
|
|
33146
33523
|
return;
|
|
33147
33524
|
case "NewExpression":
|
|
33148
|
-
|
|
33149
|
-
expr.arguments.forEach((arg) =>
|
|
33525
|
+
walkExpression2(expr.callee, add, ctx);
|
|
33526
|
+
expr.arguments.forEach((arg) => walkExpression2(arg, add, ctx));
|
|
33150
33527
|
return;
|
|
33151
33528
|
case "ArrowFunction": {
|
|
33152
33529
|
const shadowed = new Set(ctx.shadowed);
|
|
33153
33530
|
expr.params.forEach((p) => shadowed.add(p.name));
|
|
33154
33531
|
if (expr.isExpression) {
|
|
33155
|
-
|
|
33532
|
+
walkExpression2(expr.body, add, { inFunctionBody: true, shadowed });
|
|
33156
33533
|
return;
|
|
33157
33534
|
}
|
|
33158
|
-
|
|
33535
|
+
walkBlocks2(expr.body, add, { inFunctionBody: true, shadowed });
|
|
33159
33536
|
return;
|
|
33160
33537
|
}
|
|
33161
33538
|
case "FunctionExpression": {
|
|
33162
33539
|
const shadowed = new Set(ctx.shadowed);
|
|
33163
33540
|
expr.params.forEach((p) => shadowed.add(p.name));
|
|
33164
|
-
|
|
33541
|
+
walkBlocks2(expr.body, add, { inFunctionBody: true, shadowed });
|
|
33165
33542
|
return;
|
|
33166
33543
|
}
|
|
33167
33544
|
case "AssignmentExpression":
|
|
33168
|
-
|
|
33169
|
-
|
|
33545
|
+
walkExpression2(expr.left, add, ctx);
|
|
33546
|
+
walkExpression2(expr.right, add, ctx);
|
|
33170
33547
|
return;
|
|
33171
33548
|
case "UpdateExpression":
|
|
33172
|
-
|
|
33549
|
+
walkExpression2(expr.argument, add, ctx);
|
|
33173
33550
|
return;
|
|
33174
33551
|
case "JSXElement":
|
|
33175
33552
|
if (typeof expr.tagName !== "string") {
|
|
33176
|
-
|
|
33553
|
+
walkExpression2(expr.tagName, add, ctx);
|
|
33177
33554
|
}
|
|
33178
33555
|
expr.attributes.forEach((attr) => {
|
|
33179
33556
|
if (attr.isSpread && attr.spreadExpr) {
|
|
33180
|
-
|
|
33557
|
+
walkExpression2(attr.spreadExpr, add, ctx);
|
|
33181
33558
|
} else if (attr.value) {
|
|
33182
|
-
|
|
33559
|
+
walkExpression2(attr.value, add, ctx);
|
|
33183
33560
|
}
|
|
33184
33561
|
});
|
|
33185
33562
|
expr.children.forEach((child) => {
|
|
33186
33563
|
if (child.kind === "expression") {
|
|
33187
|
-
|
|
33564
|
+
walkExpression2(child.value, add, ctx);
|
|
33188
33565
|
} else if (child.kind === "element") {
|
|
33189
|
-
|
|
33566
|
+
walkExpression2(child.value, add, ctx);
|
|
33190
33567
|
}
|
|
33191
33568
|
});
|
|
33192
33569
|
return;
|
|
@@ -33194,16 +33571,16 @@ function walkExpression(expr, add, ctx) {
|
|
|
33194
33571
|
return;
|
|
33195
33572
|
}
|
|
33196
33573
|
}
|
|
33197
|
-
function
|
|
33574
|
+
function walkBlocks2(blocks, add, ctx) {
|
|
33198
33575
|
for (const block of blocks) {
|
|
33199
33576
|
for (const instr of block.instructions) {
|
|
33200
33577
|
if (instr.kind === "Assign") {
|
|
33201
|
-
|
|
33578
|
+
walkExpression2(instr.value, add, ctx);
|
|
33202
33579
|
if (instr.declarationKind) {
|
|
33203
33580
|
ctx.shadowed.add(instr.target.name);
|
|
33204
33581
|
}
|
|
33205
33582
|
} else if (instr.kind === "Expression") {
|
|
33206
|
-
|
|
33583
|
+
walkExpression2(instr.value, add, ctx);
|
|
33207
33584
|
} else if (instr.kind === "Phi") {
|
|
33208
33585
|
instr.sources.forEach((src) => {
|
|
33209
33586
|
if (!ctx.shadowed.has(src.id.name)) add(src.id.name, ctx.inFunctionBody);
|
|
@@ -33222,7 +33599,7 @@ function walkBlocks(blocks, add, ctx) {
|
|
|
33222
33599
|
function collectExpressionIdentifiers2(expr, deep = false) {
|
|
33223
33600
|
const deps = /* @__PURE__ */ new Set();
|
|
33224
33601
|
const collect = (name) => deps.add(name);
|
|
33225
|
-
|
|
33602
|
+
walkExpression2(expr, (name, _inFunctionBody) => collect(name), {
|
|
33226
33603
|
inFunctionBody: deep,
|
|
33227
33604
|
shadowed: /* @__PURE__ */ new Set()
|
|
33228
33605
|
});
|
|
@@ -33803,6 +34180,506 @@ function getRootIdentifier(expr, t4) {
|
|
|
33803
34180
|
return null;
|
|
33804
34181
|
}
|
|
33805
34182
|
|
|
34183
|
+
// src/tooling/analyze.ts
|
|
34184
|
+
import { parseSync, transformSync } from "@babel/core";
|
|
34185
|
+
|
|
34186
|
+
// src/tooling/trace-infer.ts
|
|
34187
|
+
var TRACE_REGEX_ESCAPES = /[.*+?^${}()|[\]\\]/g;
|
|
34188
|
+
var IDENTIFIER_NAME = /^[A-Za-z_$][\w$]*$/;
|
|
34189
|
+
function isIdentifierName(name) {
|
|
34190
|
+
return IDENTIFIER_NAME.test(name);
|
|
34191
|
+
}
|
|
34192
|
+
function lineContainsIdentifier(lineText, identifier2) {
|
|
34193
|
+
const pattern = new RegExp(`\\b${identifier2.replace(TRACE_REGEX_ESCAPES, "\\$&")}\\b`);
|
|
34194
|
+
return pattern.test(lineText);
|
|
34195
|
+
}
|
|
34196
|
+
function lineContainsAnyIdentifier(lineText, identifiers) {
|
|
34197
|
+
for (const id of identifiers) {
|
|
34198
|
+
if (lineContainsIdentifier(lineText, id)) return true;
|
|
34199
|
+
}
|
|
34200
|
+
return false;
|
|
34201
|
+
}
|
|
34202
|
+
function pushTraceMarker(markersByLine, line, marker) {
|
|
34203
|
+
const markers = markersByLine.get(line);
|
|
34204
|
+
if (!markers) {
|
|
34205
|
+
markersByLine.set(line, [marker]);
|
|
34206
|
+
return;
|
|
34207
|
+
}
|
|
34208
|
+
const duplicate = markers.some(
|
|
34209
|
+
(existing) => existing.kind === marker.kind && existing.label === marker.label
|
|
34210
|
+
);
|
|
34211
|
+
if (!duplicate) markers.push(marker);
|
|
34212
|
+
}
|
|
34213
|
+
function inferReactiveLocalNames(startLine, endLine, sourceLines, baseReactiveNames) {
|
|
34214
|
+
const reactiveNames = new Set(baseReactiveNames);
|
|
34215
|
+
const declarationLines = [];
|
|
34216
|
+
const declarationPattern = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(.+?)(?:;)?$/;
|
|
34217
|
+
for (let line = startLine; line <= endLine; line++) {
|
|
34218
|
+
const text = (sourceLines[line - 1] ?? "").trim();
|
|
34219
|
+
if (!text) continue;
|
|
34220
|
+
const withoutComment = text.replace(/\/\/.*$/, "").trim();
|
|
34221
|
+
if (!withoutComment) continue;
|
|
34222
|
+
const match = withoutComment.match(declarationPattern);
|
|
34223
|
+
if (!match) continue;
|
|
34224
|
+
const name = match[1];
|
|
34225
|
+
const expression = match[2];
|
|
34226
|
+
if (!name || !expression) continue;
|
|
34227
|
+
declarationLines.push({ name, expression });
|
|
34228
|
+
}
|
|
34229
|
+
let changed = true;
|
|
34230
|
+
while (changed) {
|
|
34231
|
+
changed = false;
|
|
34232
|
+
for (const declaration of declarationLines) {
|
|
34233
|
+
if (reactiveNames.has(declaration.name)) continue;
|
|
34234
|
+
if (!lineContainsAnyIdentifier(declaration.expression, reactiveNames)) continue;
|
|
34235
|
+
reactiveNames.add(declaration.name);
|
|
34236
|
+
changed = true;
|
|
34237
|
+
}
|
|
34238
|
+
}
|
|
34239
|
+
return reactiveNames;
|
|
34240
|
+
}
|
|
34241
|
+
function isStateCallInstruction(instr) {
|
|
34242
|
+
if (instr.kind !== "Assign") return false;
|
|
34243
|
+
const value = instr.value;
|
|
34244
|
+
return value.kind === "CallExpression" && value.callee.kind === "Identifier" && value.callee.name === "$state";
|
|
34245
|
+
}
|
|
34246
|
+
function collectStateDeclNames(fn) {
|
|
34247
|
+
const result = [];
|
|
34248
|
+
for (const block of fn.blocks) {
|
|
34249
|
+
for (const instr of block.instructions) {
|
|
34250
|
+
if (!isStateCallInstruction(instr) || !instr.loc) continue;
|
|
34251
|
+
const name = deSSAVarName(instr.target.name);
|
|
34252
|
+
if (!isIdentifierName(name)) continue;
|
|
34253
|
+
result.push({ name, line: instr.loc.start.line });
|
|
34254
|
+
}
|
|
34255
|
+
}
|
|
34256
|
+
return result;
|
|
34257
|
+
}
|
|
34258
|
+
function expressionContainsEffectCall(instr) {
|
|
34259
|
+
const value = instr.kind === "Assign" || instr.kind === "Expression" ? instr.value : null;
|
|
34260
|
+
if (!value || !instr.loc) return null;
|
|
34261
|
+
let found = false;
|
|
34262
|
+
walkExpression(value, (expr) => {
|
|
34263
|
+
if (expr.kind === "CallExpression" && expr.callee.kind === "Identifier" && deSSAVarName(expr.callee.name) === "$effect") {
|
|
34264
|
+
found = true;
|
|
34265
|
+
}
|
|
34266
|
+
});
|
|
34267
|
+
return found ? instr.loc.start.line : null;
|
|
34268
|
+
}
|
|
34269
|
+
function flattenRegions2(regions) {
|
|
34270
|
+
if (!regions || regions.length === 0) return [];
|
|
34271
|
+
const result = [];
|
|
34272
|
+
const visit = (region) => {
|
|
34273
|
+
result.push(region);
|
|
34274
|
+
region.children?.forEach((child) => visit(child));
|
|
34275
|
+
};
|
|
34276
|
+
regions.forEach((region) => visit(region));
|
|
34277
|
+
return result;
|
|
34278
|
+
}
|
|
34279
|
+
function findContainingRegion2(line, flatRegions) {
|
|
34280
|
+
let best;
|
|
34281
|
+
for (const region of flatRegions) {
|
|
34282
|
+
if (region.startLine === void 0 || region.endLine === void 0 || line < region.startLine || line > region.endLine) {
|
|
34283
|
+
continue;
|
|
34284
|
+
}
|
|
34285
|
+
const bestSpan = best && best.startLine !== void 0 && best.endLine !== void 0 ? best.endLine - best.startLine : Number.POSITIVE_INFINITY;
|
|
34286
|
+
const span = region.endLine - region.startLine;
|
|
34287
|
+
if (span <= bestSpan) best = region;
|
|
34288
|
+
}
|
|
34289
|
+
return best;
|
|
34290
|
+
}
|
|
34291
|
+
function inferTraceMarkersForComponent(input) {
|
|
34292
|
+
const { fn, sourceLines, startLine, endLine, verbosity, regions } = input;
|
|
34293
|
+
const markersByLine = /* @__PURE__ */ new Map();
|
|
34294
|
+
pushTraceMarker(markersByLine, startLine, {
|
|
34295
|
+
kind: "once",
|
|
34296
|
+
label: "Component setup runs on mount"
|
|
34297
|
+
});
|
|
34298
|
+
const stateDecls = collectStateDeclNames(fn);
|
|
34299
|
+
const reactiveNames = inferReactiveLocalNames(
|
|
34300
|
+
startLine,
|
|
34301
|
+
endLine,
|
|
34302
|
+
sourceLines,
|
|
34303
|
+
stateDecls.map((item) => item.name)
|
|
34304
|
+
);
|
|
34305
|
+
for (const stateDecl of stateDecls) {
|
|
34306
|
+
pushTraceMarker(markersByLine, stateDecl.line, {
|
|
34307
|
+
kind: "once",
|
|
34308
|
+
label: "Signal initialization runs once"
|
|
34309
|
+
});
|
|
34310
|
+
}
|
|
34311
|
+
for (const block of fn.blocks) {
|
|
34312
|
+
for (const instr of block.instructions) {
|
|
34313
|
+
const line = expressionContainsEffectCall(instr);
|
|
34314
|
+
if (!line || line < startLine || line > endLine) continue;
|
|
34315
|
+
pushTraceMarker(markersByLine, line, {
|
|
34316
|
+
kind: "effect",
|
|
34317
|
+
label: "Effect reruns when dependencies change"
|
|
34318
|
+
});
|
|
34319
|
+
}
|
|
34320
|
+
}
|
|
34321
|
+
const flatRegions = flattenRegions2(regions);
|
|
34322
|
+
for (let line = startLine; line <= endLine; line++) {
|
|
34323
|
+
const lineText = sourceLines[line - 1] ?? "";
|
|
34324
|
+
if (!lineText) continue;
|
|
34325
|
+
const hasReactiveName = lineContainsAnyIdentifier(lineText, reactiveNames);
|
|
34326
|
+
if (hasReactiveName && /\{[^}]*\b[A-Za-z_$][\w$]*\b[^}]*\}/.test(lineText)) {
|
|
34327
|
+
pushTraceMarker(markersByLine, line, {
|
|
34328
|
+
kind: "reactive",
|
|
34329
|
+
label: "JSX expression updates with reactive values"
|
|
34330
|
+
});
|
|
34331
|
+
}
|
|
34332
|
+
if (hasReactiveName && /\bconsole\.(?:log|debug|info|warn|error)\s*\(/.test(lineText)) {
|
|
34333
|
+
pushTraceMarker(markersByLine, line, {
|
|
34334
|
+
kind: "reactive",
|
|
34335
|
+
label: "Statement reruns when reactive values change"
|
|
34336
|
+
});
|
|
34337
|
+
}
|
|
34338
|
+
if (/\b(?:\$effect|effect)\s*\(/.test(lineText)) {
|
|
34339
|
+
pushTraceMarker(markersByLine, line, {
|
|
34340
|
+
kind: "effect",
|
|
34341
|
+
label: "Effect callback executes reactively"
|
|
34342
|
+
});
|
|
34343
|
+
}
|
|
34344
|
+
if (verbosity === "verbose" && !hasReactiveName && /\{[^}]*\}/.test(lineText)) {
|
|
34345
|
+
pushTraceMarker(markersByLine, line, {
|
|
34346
|
+
kind: "once",
|
|
34347
|
+
label: "JSX expression runs during setup only"
|
|
34348
|
+
});
|
|
34349
|
+
}
|
|
34350
|
+
if (/\bconsole\.(?:log|debug|info|warn|error)\s*\(/.test(lineText) && !hasReactiveName && line !== startLine) {
|
|
34351
|
+
pushTraceMarker(markersByLine, line, {
|
|
34352
|
+
kind: "once",
|
|
34353
|
+
label: "Statement runs only during setup"
|
|
34354
|
+
});
|
|
34355
|
+
}
|
|
34356
|
+
const containingRegion = findContainingRegion2(line, flatRegions);
|
|
34357
|
+
if (!containingRegion) continue;
|
|
34358
|
+
const markers = markersByLine.get(line);
|
|
34359
|
+
if (!markers) continue;
|
|
34360
|
+
for (const marker of markers) {
|
|
34361
|
+
marker.regionId = containingRegion.id;
|
|
34362
|
+
marker.deps = containingRegion.dependencies;
|
|
34363
|
+
}
|
|
34364
|
+
}
|
|
34365
|
+
return [...markersByLine.entries()].sort((a, b) => a[0] - b[0]).map(([line, markers]) => ({ line, markers }));
|
|
34366
|
+
}
|
|
34367
|
+
|
|
34368
|
+
// src/tooling/analyze.ts
|
|
34369
|
+
function mergeLoc(a, b) {
|
|
34370
|
+
if (!a) return b ?? null;
|
|
34371
|
+
if (!b) return a;
|
|
34372
|
+
const start = b.start.line < a.start.line || b.start.line === a.start.line && b.start.column < a.start.column ? b.start : a.start;
|
|
34373
|
+
const end = b.end.line > a.end.line || b.end.line === a.end.line && b.end.column > a.end.column ? b.end : a.end;
|
|
34374
|
+
return {
|
|
34375
|
+
start,
|
|
34376
|
+
end,
|
|
34377
|
+
filename: a.filename ?? b.filename,
|
|
34378
|
+
identifierName: a.identifierName ?? b.identifierName
|
|
34379
|
+
};
|
|
34380
|
+
}
|
|
34381
|
+
function expressionContainsMacroCall(expr, macroName) {
|
|
34382
|
+
let found = false;
|
|
34383
|
+
const visit = (value) => {
|
|
34384
|
+
if (found) return;
|
|
34385
|
+
if (value.kind === "CallExpression" && value.callee.kind === "Identifier" && deSSAVarName(value.callee.name) === macroName) {
|
|
34386
|
+
found = true;
|
|
34387
|
+
return;
|
|
34388
|
+
}
|
|
34389
|
+
switch (value.kind) {
|
|
34390
|
+
case "CallExpression":
|
|
34391
|
+
case "OptionalCallExpression":
|
|
34392
|
+
visit(value.callee);
|
|
34393
|
+
value.arguments.forEach((arg) => visit(arg));
|
|
34394
|
+
return;
|
|
34395
|
+
case "MemberExpression":
|
|
34396
|
+
case "OptionalMemberExpression":
|
|
34397
|
+
visit(value.object);
|
|
34398
|
+
if (value.computed) visit(value.property);
|
|
34399
|
+
return;
|
|
34400
|
+
case "BinaryExpression":
|
|
34401
|
+
case "LogicalExpression":
|
|
34402
|
+
visit(value.left);
|
|
34403
|
+
visit(value.right);
|
|
34404
|
+
return;
|
|
34405
|
+
case "UnaryExpression":
|
|
34406
|
+
case "AwaitExpression":
|
|
34407
|
+
case "UpdateExpression":
|
|
34408
|
+
case "SpreadElement":
|
|
34409
|
+
visit(value.argument);
|
|
34410
|
+
return;
|
|
34411
|
+
case "ConditionalExpression":
|
|
34412
|
+
visit(value.test);
|
|
34413
|
+
visit(value.consequent);
|
|
34414
|
+
visit(value.alternate);
|
|
34415
|
+
return;
|
|
34416
|
+
case "ArrayExpression":
|
|
34417
|
+
value.elements.forEach((el) => visit(el));
|
|
34418
|
+
return;
|
|
34419
|
+
case "ObjectExpression":
|
|
34420
|
+
value.properties.forEach((prop) => {
|
|
34421
|
+
if (prop.kind === "SpreadElement") {
|
|
34422
|
+
visit(prop.argument);
|
|
34423
|
+
return;
|
|
34424
|
+
}
|
|
34425
|
+
if (prop.computed) visit(prop.key);
|
|
34426
|
+
visit(prop.value);
|
|
34427
|
+
});
|
|
34428
|
+
return;
|
|
34429
|
+
case "TemplateLiteral":
|
|
34430
|
+
value.expressions.forEach((item) => visit(item));
|
|
34431
|
+
return;
|
|
34432
|
+
case "AssignmentExpression":
|
|
34433
|
+
visit(value.left);
|
|
34434
|
+
visit(value.right);
|
|
34435
|
+
return;
|
|
34436
|
+
case "SequenceExpression":
|
|
34437
|
+
value.expressions.forEach((item) => visit(item));
|
|
34438
|
+
return;
|
|
34439
|
+
case "YieldExpression":
|
|
34440
|
+
if (value.argument) visit(value.argument);
|
|
34441
|
+
return;
|
|
34442
|
+
case "TaggedTemplateExpression":
|
|
34443
|
+
visit(value.tag);
|
|
34444
|
+
value.quasi.expressions.forEach((item) => visit(item));
|
|
34445
|
+
return;
|
|
34446
|
+
case "ImportExpression":
|
|
34447
|
+
visit(value.source);
|
|
34448
|
+
return;
|
|
34449
|
+
case "ArrowFunction":
|
|
34450
|
+
if (Array.isArray(value.body)) {
|
|
34451
|
+
value.body.forEach((block) => {
|
|
34452
|
+
block.instructions.forEach((instr) => {
|
|
34453
|
+
if (instr.kind === "Assign" || instr.kind === "Expression") {
|
|
34454
|
+
visit(instr.value);
|
|
34455
|
+
}
|
|
34456
|
+
});
|
|
34457
|
+
});
|
|
34458
|
+
} else {
|
|
34459
|
+
visit(value.body);
|
|
34460
|
+
}
|
|
34461
|
+
return;
|
|
34462
|
+
case "FunctionExpression":
|
|
34463
|
+
value.body.forEach((block) => {
|
|
34464
|
+
block.instructions.forEach((instr) => {
|
|
34465
|
+
if (instr.kind === "Assign" || instr.kind === "Expression") {
|
|
34466
|
+
visit(instr.value);
|
|
34467
|
+
}
|
|
34468
|
+
});
|
|
34469
|
+
});
|
|
34470
|
+
return;
|
|
34471
|
+
case "JSXElement":
|
|
34472
|
+
if (typeof value.tagName !== "string") visit(value.tagName);
|
|
34473
|
+
value.attributes.forEach((attr) => {
|
|
34474
|
+
if (attr.isSpread && attr.spreadExpr) {
|
|
34475
|
+
visit(attr.spreadExpr);
|
|
34476
|
+
} else if (attr.value) {
|
|
34477
|
+
visit(attr.value);
|
|
34478
|
+
}
|
|
34479
|
+
});
|
|
34480
|
+
value.children.forEach((child) => {
|
|
34481
|
+
if (child.kind === "expression") visit(child.value);
|
|
34482
|
+
if (child.kind === "element") visit(child.value);
|
|
34483
|
+
});
|
|
34484
|
+
return;
|
|
34485
|
+
case "Identifier":
|
|
34486
|
+
case "Literal":
|
|
34487
|
+
case "MetaProperty":
|
|
34488
|
+
case "NewExpression":
|
|
34489
|
+
case "ClassExpression":
|
|
34490
|
+
case "ThisExpression":
|
|
34491
|
+
case "SuperExpression":
|
|
34492
|
+
if (value.kind === "NewExpression") {
|
|
34493
|
+
visit(value.callee);
|
|
34494
|
+
value.arguments.forEach((arg) => visit(arg));
|
|
34495
|
+
}
|
|
34496
|
+
if (value.kind === "ClassExpression" && value.superClass) visit(value.superClass);
|
|
34497
|
+
return;
|
|
34498
|
+
default:
|
|
34499
|
+
return;
|
|
34500
|
+
}
|
|
34501
|
+
};
|
|
34502
|
+
visit(expr);
|
|
34503
|
+
return found;
|
|
34504
|
+
}
|
|
34505
|
+
function instructionContainsMacroCall(instruction, macroName) {
|
|
34506
|
+
if (instruction.kind !== "Assign" && instruction.kind !== "Expression") return false;
|
|
34507
|
+
return expressionContainsMacroCall(instruction.value, macroName);
|
|
34508
|
+
}
|
|
34509
|
+
function functionUsesMacro(fn, macroName) {
|
|
34510
|
+
for (const block of fn.blocks) {
|
|
34511
|
+
for (const instruction of block.instructions) {
|
|
34512
|
+
if (instructionContainsMacroCall(instruction, macroName)) return true;
|
|
34513
|
+
}
|
|
34514
|
+
const term = block.terminator;
|
|
34515
|
+
if ("argument" in term && term.argument && expressionContainsMacroCall(term.argument, macroName)) {
|
|
34516
|
+
return true;
|
|
34517
|
+
}
|
|
34518
|
+
if (term.kind === "Branch" && expressionContainsMacroCall(term.test, macroName)) {
|
|
34519
|
+
return true;
|
|
34520
|
+
}
|
|
34521
|
+
if (term.kind === "Switch") {
|
|
34522
|
+
if (expressionContainsMacroCall(term.discriminant, macroName)) return true;
|
|
34523
|
+
if (term.cases.some((entry) => entry.test && expressionContainsMacroCall(entry.test, macroName))) {
|
|
34524
|
+
return true;
|
|
34525
|
+
}
|
|
34526
|
+
}
|
|
34527
|
+
}
|
|
34528
|
+
return false;
|
|
34529
|
+
}
|
|
34530
|
+
function computeRegionLoc(region, fn) {
|
|
34531
|
+
let loc = null;
|
|
34532
|
+
for (const instruction of region.instructions) {
|
|
34533
|
+
loc = mergeLoc(loc, instruction.loc);
|
|
34534
|
+
}
|
|
34535
|
+
for (const blockId of region.blocks) {
|
|
34536
|
+
const block = fn.blocks.find((entry) => entry.id === blockId);
|
|
34537
|
+
if (!block) continue;
|
|
34538
|
+
loc = mergeLoc(loc, block.terminator.loc);
|
|
34539
|
+
}
|
|
34540
|
+
return loc;
|
|
34541
|
+
}
|
|
34542
|
+
function regionToSerializable(region, fn) {
|
|
34543
|
+
const loc = computeRegionLoc(region, fn);
|
|
34544
|
+
return {
|
|
34545
|
+
id: region.id,
|
|
34546
|
+
startLine: loc?.start.line,
|
|
34547
|
+
startColumn: loc?.start.column,
|
|
34548
|
+
endLine: loc?.end.line,
|
|
34549
|
+
endColumn: loc?.end.column,
|
|
34550
|
+
dependencies: [...region.dependencies].map(deSSAVarName),
|
|
34551
|
+
declarations: [...region.declarations].map(deSSAVarName),
|
|
34552
|
+
hasControlFlow: region.hasControlFlow,
|
|
34553
|
+
hasReactiveWrites: region.declarations.size > 0,
|
|
34554
|
+
children: region.children.map((child) => regionToSerializable(child, fn))
|
|
34555
|
+
};
|
|
34556
|
+
}
|
|
34557
|
+
function warningSeverity(code) {
|
|
34558
|
+
const diagnosticCodes = new Set(getAllDiagnosticCodes());
|
|
34559
|
+
if (!diagnosticCodes.has(code)) return "warning" /* Warning */;
|
|
34560
|
+
return getDiagnosticInfo(code).severity;
|
|
34561
|
+
}
|
|
34562
|
+
function normalizeWarningToDiagnostic(warning) {
|
|
34563
|
+
return {
|
|
34564
|
+
code: warning.code,
|
|
34565
|
+
message: warning.message,
|
|
34566
|
+
severity: warningSeverity(warning.code),
|
|
34567
|
+
line: warning.line,
|
|
34568
|
+
column: warning.column
|
|
34569
|
+
};
|
|
34570
|
+
}
|
|
34571
|
+
function normalizeThrownError(error) {
|
|
34572
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
34573
|
+
return {
|
|
34574
|
+
code: "FICT-COMPILE",
|
|
34575
|
+
message,
|
|
34576
|
+
severity: "error" /* Error */,
|
|
34577
|
+
line: 0,
|
|
34578
|
+
column: 0
|
|
34579
|
+
};
|
|
34580
|
+
}
|
|
34581
|
+
function analyzeDiagnostics(code, fileName, options) {
|
|
34582
|
+
const warnings = [];
|
|
34583
|
+
const pluginOptions = {
|
|
34584
|
+
dev: true,
|
|
34585
|
+
filename: fileName,
|
|
34586
|
+
emitModuleMetadata: false,
|
|
34587
|
+
strictGuarantee: false,
|
|
34588
|
+
warningLevels: {
|
|
34589
|
+
...options.compilerOptions?.warningLevels ?? {},
|
|
34590
|
+
"FICT-R004": "warn"
|
|
34591
|
+
},
|
|
34592
|
+
...options.compilerOptions,
|
|
34593
|
+
onWarn: (warning) => warnings.push(warning)
|
|
34594
|
+
};
|
|
34595
|
+
try {
|
|
34596
|
+
transformSync(code, {
|
|
34597
|
+
filename: fileName,
|
|
34598
|
+
configFile: false,
|
|
34599
|
+
babelrc: false,
|
|
34600
|
+
sourceType: "module",
|
|
34601
|
+
parserOpts: {
|
|
34602
|
+
sourceType: "module",
|
|
34603
|
+
plugins: ["typescript", "jsx"],
|
|
34604
|
+
allowReturnOutsideFunction: true
|
|
34605
|
+
},
|
|
34606
|
+
plugins: [[index_default, pluginOptions]],
|
|
34607
|
+
generatorOpts: {
|
|
34608
|
+
compact: false
|
|
34609
|
+
}
|
|
34610
|
+
});
|
|
34611
|
+
} catch (error) {
|
|
34612
|
+
return [...warnings.map(normalizeWarningToDiagnostic), normalizeThrownError(error)];
|
|
34613
|
+
}
|
|
34614
|
+
return warnings.map(normalizeWarningToDiagnostic);
|
|
34615
|
+
}
|
|
34616
|
+
function shouldIncludeFunction(fn) {
|
|
34617
|
+
return functionContainsJSX(fn) || functionUsesMacro(fn, "$state") || functionUsesMacro(fn, "$effect");
|
|
34618
|
+
}
|
|
34619
|
+
function parseFileAst(code, fileName) {
|
|
34620
|
+
const ast = parseSync(code, {
|
|
34621
|
+
filename: fileName,
|
|
34622
|
+
sourceType: "module",
|
|
34623
|
+
parserOpts: {
|
|
34624
|
+
sourceType: "module",
|
|
34625
|
+
plugins: ["typescript", "jsx"],
|
|
34626
|
+
allowReturnOutsideFunction: true
|
|
34627
|
+
}
|
|
34628
|
+
});
|
|
34629
|
+
if (!ast || ast.type !== "File") {
|
|
34630
|
+
throw new Error("Failed to parse source file for Fict analysis.");
|
|
34631
|
+
}
|
|
34632
|
+
return ast;
|
|
34633
|
+
}
|
|
34634
|
+
function analyzeFictFile(code, fileName, options = {}) {
|
|
34635
|
+
const includeRegions = options.includeRegions ?? true;
|
|
34636
|
+
const includeDiagnostics = options.includeDiagnostics ?? true;
|
|
34637
|
+
const verbosity = options.verbosity ?? "minimal";
|
|
34638
|
+
const ast = parseFileAst(code, fileName);
|
|
34639
|
+
const hir = buildHIR(
|
|
34640
|
+
ast,
|
|
34641
|
+
{
|
|
34642
|
+
state: /* @__PURE__ */ new Set(["$state"]),
|
|
34643
|
+
effect: /* @__PURE__ */ new Set(["$effect"])
|
|
34644
|
+
},
|
|
34645
|
+
{
|
|
34646
|
+
dev: true,
|
|
34647
|
+
fileName
|
|
34648
|
+
}
|
|
34649
|
+
);
|
|
34650
|
+
const sourceLines = code.split(/\r?\n/);
|
|
34651
|
+
const components = [];
|
|
34652
|
+
for (const fn of hir.functions) {
|
|
34653
|
+
if (!fn.loc || !shouldIncludeFunction(fn)) continue;
|
|
34654
|
+
const startLine = fn.loc.start.line;
|
|
34655
|
+
const endLine = fn.loc.end.line;
|
|
34656
|
+
const scopeResult = analyzeReactiveScopesWithSSA(fn);
|
|
34657
|
+
const regionResult = generateRegions(fn, scopeResult);
|
|
34658
|
+
const regions = includeRegions ? regionResult.topLevelRegions.map((region) => regionToSerializable(region, fn)) : void 0;
|
|
34659
|
+
const trace = inferTraceMarkersForComponent({
|
|
34660
|
+
fn,
|
|
34661
|
+
sourceLines,
|
|
34662
|
+
startLine,
|
|
34663
|
+
endLine,
|
|
34664
|
+
verbosity,
|
|
34665
|
+
regions
|
|
34666
|
+
});
|
|
34667
|
+
components.push({
|
|
34668
|
+
name: fn.name ?? "<anonymous>",
|
|
34669
|
+
startLine,
|
|
34670
|
+
endLine,
|
|
34671
|
+
trace,
|
|
34672
|
+
regions
|
|
34673
|
+
});
|
|
34674
|
+
}
|
|
34675
|
+
const diagnostics = includeDiagnostics ? analyzeDiagnostics(code, fileName, options) : [];
|
|
34676
|
+
return {
|
|
34677
|
+
fileName,
|
|
34678
|
+
components,
|
|
34679
|
+
diagnostics
|
|
34680
|
+
};
|
|
34681
|
+
}
|
|
34682
|
+
|
|
33806
34683
|
// src/index.ts
|
|
33807
34684
|
function stripMacroImports(path2, t4) {
|
|
33808
34685
|
path2.traverse({
|
|
@@ -34696,46 +35573,77 @@ function createHIREntrypointVisitor(t4, options) {
|
|
|
34696
35573
|
path2.traverse({
|
|
34697
35574
|
JSXExpressionContainer(exprPath) {
|
|
34698
35575
|
const expr = exprPath.node.expression;
|
|
34699
|
-
if (!t4.isCallExpression(expr)) return;
|
|
34700
|
-
if (!t4.isMemberExpression(expr.callee) || !t4.isIdentifier(expr.callee.property, { name: "map" })) {
|
|
35576
|
+
if (!t4.isCallExpression(expr) && !t4.isOptionalCallExpression(expr)) return;
|
|
35577
|
+
if (!t4.isMemberExpression(expr.callee) && !t4.isOptionalMemberExpression(expr.callee) || !t4.isIdentifier(expr.callee.property, { name: "map" })) {
|
|
34701
35578
|
return;
|
|
34702
35579
|
}
|
|
34703
|
-
const
|
|
34704
|
-
if (!
|
|
34705
|
-
const
|
|
34706
|
-
|
|
34707
|
-
|
|
34708
|
-
const ret = fn.body.body.find((stmt) => t4.isReturnStatement(stmt));
|
|
34709
|
-
if (ret && t4.isReturnStatement(ret) && ret.argument && (t4.isJSXElement(ret.argument) || t4.isJSXFragment(ret.argument))) {
|
|
34710
|
-
return ret.argument;
|
|
34711
|
-
}
|
|
34712
|
-
}
|
|
34713
|
-
return null;
|
|
34714
|
-
};
|
|
34715
|
-
const jsx = getReturnedJsx(cb);
|
|
34716
|
-
if (!jsx) return;
|
|
34717
|
-
if (t4.isJSXFragment(jsx)) {
|
|
34718
|
-
warn({
|
|
34719
|
-
code: "FICT-J002",
|
|
34720
|
-
message: "Missing key prop in list rendering.",
|
|
34721
|
-
fileName,
|
|
34722
|
-
line: expr.loc?.start.line ?? 0,
|
|
34723
|
-
column: expr.loc ? expr.loc.start.column + 1 : 0
|
|
34724
|
-
});
|
|
35580
|
+
const callExprPath = exprPath.get("expression");
|
|
35581
|
+
if (!callExprPath.isCallExpression() && !callExprPath.isOptionalCallExpression()) return;
|
|
35582
|
+
const argPaths = callExprPath.get("arguments");
|
|
35583
|
+
const cbPath = Array.isArray(argPaths) ? argPaths[0] : void 0;
|
|
35584
|
+
if (!cbPath || !cbPath.isArrowFunctionExpression() && !cbPath.isFunctionExpression()) {
|
|
34725
35585
|
return;
|
|
34726
35586
|
}
|
|
34727
|
-
|
|
34728
|
-
|
|
34729
|
-
|
|
34730
|
-
|
|
34731
|
-
|
|
34732
|
-
|
|
35587
|
+
const getReturnedJsx = (fnPath) => {
|
|
35588
|
+
const collectReturnedJsxFromExpression = (node, returned2) => {
|
|
35589
|
+
if (!node) return;
|
|
35590
|
+
if (t4.isJSXElement(node) || t4.isJSXFragment(node)) {
|
|
35591
|
+
returned2.push(node);
|
|
35592
|
+
return;
|
|
35593
|
+
}
|
|
35594
|
+
if (t4.isConditionalExpression(node)) {
|
|
35595
|
+
collectReturnedJsxFromExpression(node.consequent, returned2);
|
|
35596
|
+
collectReturnedJsxFromExpression(node.alternate, returned2);
|
|
35597
|
+
return;
|
|
35598
|
+
}
|
|
35599
|
+
if (t4.isLogicalExpression(node)) {
|
|
35600
|
+
collectReturnedJsxFromExpression(node.left, returned2);
|
|
35601
|
+
collectReturnedJsxFromExpression(node.right, returned2);
|
|
35602
|
+
return;
|
|
35603
|
+
}
|
|
35604
|
+
if (t4.isSequenceExpression(node)) {
|
|
35605
|
+
const tail = node.expressions[node.expressions.length - 1];
|
|
35606
|
+
collectReturnedJsxFromExpression(tail, returned2);
|
|
35607
|
+
return;
|
|
35608
|
+
}
|
|
35609
|
+
if (t4.isParenthesizedExpression(node)) {
|
|
35610
|
+
collectReturnedJsxFromExpression(node.expression, returned2);
|
|
35611
|
+
return;
|
|
35612
|
+
}
|
|
35613
|
+
if (t4.isTSAsExpression(node) || t4.isTSTypeAssertion(node) || t4.isTSNonNullExpression(node) || t4.isTSSatisfiesExpression(node) || t4.isTypeCastExpression(node)) {
|
|
35614
|
+
collectReturnedJsxFromExpression(node.expression, returned2);
|
|
35615
|
+
}
|
|
35616
|
+
};
|
|
35617
|
+
const fn = fnPath.node;
|
|
35618
|
+
const returned = [];
|
|
35619
|
+
if (!t4.isBlockStatement(fn.body)) {
|
|
35620
|
+
collectReturnedJsxFromExpression(fn.body, returned);
|
|
35621
|
+
return returned;
|
|
34733
35622
|
}
|
|
34734
|
-
|
|
34735
|
-
|
|
35623
|
+
fnPath.get("body").traverse({
|
|
35624
|
+
Function(innerFnPath) {
|
|
35625
|
+
innerFnPath.skip();
|
|
35626
|
+
},
|
|
35627
|
+
ReturnStatement(retPath) {
|
|
35628
|
+
collectReturnedJsxFromExpression(retPath.node.argument, returned);
|
|
35629
|
+
}
|
|
35630
|
+
});
|
|
35631
|
+
return returned;
|
|
35632
|
+
};
|
|
35633
|
+
const returnedJsx = getReturnedJsx(cbPath);
|
|
35634
|
+
if (returnedJsx.length === 0) return;
|
|
35635
|
+
const hasMissingKeyBranch = returnedJsx.some((jsx) => {
|
|
35636
|
+
if (t4.isJSXFragment(jsx)) return true;
|
|
35637
|
+
let hasKey = false;
|
|
35638
|
+
for (const attr of jsx.openingElement.attributes) {
|
|
35639
|
+
if (t4.isJSXAttribute(attr) && t4.isJSXIdentifier(attr.name, { name: "key" })) {
|
|
35640
|
+
hasKey = true;
|
|
35641
|
+
break;
|
|
35642
|
+
}
|
|
34736
35643
|
}
|
|
34737
|
-
|
|
34738
|
-
|
|
35644
|
+
return !hasKey;
|
|
35645
|
+
});
|
|
35646
|
+
if (!hasMissingKeyBranch) return;
|
|
34739
35647
|
warn({
|
|
34740
35648
|
code: "FICT-J002",
|
|
34741
35649
|
message: "Missing key prop in list rendering.",
|
|
@@ -35297,9 +36205,11 @@ var createFictPlugin = declare(
|
|
|
35297
36205
|
);
|
|
35298
36206
|
var index_default = createFictPlugin;
|
|
35299
36207
|
export {
|
|
36208
|
+
analyzeFictFile,
|
|
35300
36209
|
clearModuleMetadata,
|
|
35301
36210
|
createFictPlugin,
|
|
35302
36211
|
index_default as default,
|
|
36212
|
+
inferTraceMarkersForComponent,
|
|
35303
36213
|
resolveModuleMetadata,
|
|
35304
36214
|
setModuleMetadata
|
|
35305
36215
|
};
|