@marko/language-tools 2.5.57 → 2.5.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -730,6 +730,7 @@ var Extracted = class {
730
730
  );
731
731
  }
732
732
  }
733
+ parsed;
733
734
  #generated;
734
735
  #sourceToGenerated;
735
736
  #generatedToSource;
@@ -863,7 +864,10 @@ function sortBySourceThenGenerated(a, b) {
863
864
  }
864
865
 
865
866
  // src/extractors/html/keywords.ts
866
- var builtinTagsRegex = /^(?:a(?:(?:bbr|cronym|ddress|pplet|r(?:ea|ticle)|side|udio))?|b(?:(?:ase(?:font)?|d[io]|gsound|ig|l(?:ink|ockquote)|ody|r|utton))?|c(?:a(?:nvas|ption)|enter|ite|o(?:de|l(?:group)?|mmand|ntent))|d(?:ata(?:list)?|d|e(?:l|tails)|fn|i(?:alog|r|v)|l|t)|e(?:lement|m(?:bed)?)|f(?:i(?:eldset|g(?:caption|ure))|o(?:nt|oter|rm)|rame(?:set)?)|h(?:1|2|3|4|5|6|ead(?:er)?|group|r|tml)|i(?:(?:frame|m(?:age|g)|n(?:put|s)|sindex))?|k(?:bd|eygen)|l(?:abel|egend|i(?:(?:nk|sting))?)|m(?:a(?:in|p|r(?:k|quee)|th)|e(?:nu(?:item)?|t(?:a|er))|ulticol)|n(?:av|extid|o(?:br|embed|frames|script))|o(?:bject|l|pt(?:group|ion)|utput)|p(?:(?:aram|icture|laintext|r(?:e|ogress)))?|q|r(?:bc?|p|tc?|uby)|s(?:(?:amp|cript|e(?:ction|lect)|hadow|lot|mall|ource|pa(?:cer|n)|t(?:r(?:ike|ong)|yle)|u(?:b|mmary|p)|vg))?|t(?:able|body|d|e(?:mplate|xtarea)|foot|h(?:ead)?|i(?:me|tle)|r(?:ack)?|t)|ul?|v(?:ar|ideo)|wbr|xmp)$/;
867
+ var builtinTagsRegex = (
868
+ /* cspell:disable-next-line */
869
+ /^(?:a(?:(?:bbr|cronym|ddress|pplet|r(?:ea|ticle)|side|udio))?|b(?:(?:ase(?:font)?|d[io]|gsound|ig|l(?:ink|ockquote)|ody|r|utton))?|c(?:a(?:nvas|ption)|enter|ite|o(?:de|l(?:group)?|mmand|ntent))|d(?:ata(?:list)?|d|e(?:l|tails)|fn|i(?:alog|r|v)|l|t)|e(?:lement|m(?:bed)?)|f(?:i(?:eldset|g(?:caption|ure))|o(?:nt|oter|rm)|rame(?:set)?)|h(?:1|2|3|4|5|6|ead(?:er)?|group|r|tml)|i(?:(?:frame|m(?:age|g)|n(?:put|s)|sindex))?|k(?:bd|eygen)|l(?:abel|egend|i(?:(?:nk|sting))?)|m(?:a(?:in|p|r(?:k|quee)|th)|e(?:nu(?:item)?|t(?:a|er))|ulticol)|n(?:av|extid|o(?:br|embed|frames|script))|o(?:bject|l|pt(?:group|ion)|utput)|p(?:(?:aram|icture|laintext|r(?:e|ogress)))?|q|r(?:bc?|p|tc?|uby)|s(?:(?:amp|cript|e(?:ction|lect)|hadow|lot|mall|ource|pa(?:cer|n)|t(?:r(?:ike|ong)|yle)|u(?:b|mmary|p)|vg))?|t(?:able|body|d|e(?:mplate|xtarea)|foot|h(?:ead)?|i(?:me|tle)|r(?:ack)?|t)|ul?|v(?:ar|ideo)|wbr|xmp)$/
870
+ );
867
871
  function isHTMLTag(tag) {
868
872
  return builtinTagsRegex.test(tag);
869
873
  }
@@ -1063,6 +1067,9 @@ var import_relative_import_path = require("relative-import-path");
1063
1067
  // src/extractors/script/util/attach-scopes.ts
1064
1068
  var import_compiler = require("@marko/compiler");
1065
1069
 
1070
+ // src/extractors/script/util/script-parser.ts
1071
+ var import_babel = require("@marko/compiler/internal/babel");
1072
+
1066
1073
  // src/extractors/script/util/is-text-only-script.ts
1067
1074
  function isTextOnlyScript(tag) {
1068
1075
  if (tag.nameText !== "script" || tag.args || tag.attrs || !tag.body) {
@@ -1076,17 +1083,198 @@ function isTextOnlyScript(tag) {
1076
1083
  return true;
1077
1084
  }
1078
1085
 
1086
+ // src/extractors/script/util/script-parser.ts
1087
+ var plugins = ["exportDefaultFrom", "importAssertions", "typescript"];
1088
+ var ScriptParser = class {
1089
+ #parsed;
1090
+ #cache = /* @__PURE__ */ new Map();
1091
+ constructor(parsed) {
1092
+ this.#parsed = parsed;
1093
+ }
1094
+ tagName(name) {
1095
+ return this.#templateExpressions(name);
1096
+ }
1097
+ tagShorthandId(shorthandId) {
1098
+ return this.#templateExpressions(shorthandId);
1099
+ }
1100
+ tagShorthandClassName(node) {
1101
+ return this.#templateExpressions(node);
1102
+ }
1103
+ tagVar(node) {
1104
+ const start = node.value.start - 1;
1105
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `(${this.#parsed.read(node.value)})=>0`);
1106
+ if (expr) {
1107
+ return expr.params[0];
1108
+ }
1109
+ }
1110
+ tagParams(node) {
1111
+ const start = node.start;
1112
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `(${this.#parsed.read(node.value)})=>0`);
1113
+ if (expr) {
1114
+ return expr.params;
1115
+ }
1116
+ }
1117
+ tagTypeParams(node) {
1118
+ const start = node.value.start - 1;
1119
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `<${this.#parsed.read(node.value)}>()=>0`);
1120
+ if (expr) {
1121
+ return expr.typeParameters;
1122
+ }
1123
+ }
1124
+ tagArgs(node) {
1125
+ const start = node.value.start - 2;
1126
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `_(${this.#parsed.read(node.value)})`);
1127
+ if (expr) {
1128
+ return expr.arguments;
1129
+ }
1130
+ }
1131
+ tagTypeArgs(node) {
1132
+ const start = node.value.start - 2;
1133
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `_<${this.#parsed.read(node.value)}>()`);
1134
+ if (expr) {
1135
+ return expr.typeParameters;
1136
+ }
1137
+ }
1138
+ attrValue(node) {
1139
+ const start = node.value.start;
1140
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1141
+ }
1142
+ attrSpread(node) {
1143
+ const start = node.value.start;
1144
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1145
+ }
1146
+ attrMethod(node) {
1147
+ const start = node.params.start - 2;
1148
+ const expr = this.#cache.get(start) ?? this.#expressionAt(
1149
+ start,
1150
+ `{_${this.#parsed.read({ start: node.params.start, end: node.body.end })}}`
1151
+ );
1152
+ if (expr) {
1153
+ return expr.properties[0];
1154
+ }
1155
+ }
1156
+ attrArgs(node) {
1157
+ const start = node.value.start;
1158
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1159
+ }
1160
+ placeholder(node) {
1161
+ const start = node.value.start;
1162
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1163
+ }
1164
+ scriptBody(node) {
1165
+ if (!isTextOnlyScript(node)) return;
1166
+ const start = node.body[0].start;
1167
+ const statements = this.#cache.get(start) ?? this.#statementsAt(
1168
+ start,
1169
+ this.#parsed.read({ start, end: node.body[node.body.length - 1].end })
1170
+ );
1171
+ if (statements) {
1172
+ return statements;
1173
+ }
1174
+ }
1175
+ scriptlet(node) {
1176
+ const start = node.value.start;
1177
+ const statements = this.#cache.get(start) ?? this.#statementsAt(start, this.#parsed.read(node.value));
1178
+ if (statements) {
1179
+ return statements;
1180
+ }
1181
+ }
1182
+ import(node) {
1183
+ const statements = this.#cache.get(node.start) ?? this.#statementsAt(node.start, this.#parsed.read(node));
1184
+ if (statements) {
1185
+ return statements[0];
1186
+ }
1187
+ }
1188
+ export(node) {
1189
+ const statements = this.#cache.get(node.start) ?? this.#statementsAt(node.start, this.#parsed.read(node));
1190
+ if (statements) {
1191
+ return statements[0];
1192
+ }
1193
+ }
1194
+ class(node) {
1195
+ const expr = this.#cache.get(node.start) ?? this.#expressionAt(node.start, this.#parsed.read(node));
1196
+ return expr || void 0;
1197
+ }
1198
+ static(node) {
1199
+ const start = node.start + "static ".length;
1200
+ const statements = this.#cache.get(start) ?? this.#statementsAt(start, this.#parsed.read({ start, end: node.end }));
1201
+ if (statements) {
1202
+ return statements;
1203
+ }
1204
+ }
1205
+ #templateExpressions(template) {
1206
+ const { expressions } = template;
1207
+ if (!expressions.length) return;
1208
+ const result = [];
1209
+ for (const expr of expressions) {
1210
+ const start = expr.value.start;
1211
+ const parsed = this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(expr.value));
1212
+ if (!parsed) return;
1213
+ result.push(parsed);
1214
+ }
1215
+ if (result.length) return result;
1216
+ }
1217
+ #statementsAt(startIndex, src) {
1218
+ try {
1219
+ const pos = this.#parsed.positionAt(startIndex);
1220
+ const result = (0, import_babel.parse)(src, {
1221
+ plugins,
1222
+ startIndex,
1223
+ startLine: pos.line + 1,
1224
+ startColumn: pos.character,
1225
+ strictMode: true,
1226
+ errorRecovery: true,
1227
+ sourceType: "module",
1228
+ allowUndeclaredExports: true,
1229
+ allowSuperOutsideMethod: true,
1230
+ allowAwaitOutsideFunction: true,
1231
+ allowReturnOutsideFunction: true,
1232
+ sourceFilename: this.#parsed.filename
1233
+ }).program.body;
1234
+ if (result.length) {
1235
+ this.#cache.set(startIndex, result);
1236
+ return result;
1237
+ }
1238
+ } catch {
1239
+ }
1240
+ this.#cache.set(startIndex, false);
1241
+ }
1242
+ #expressionAt(startIndex, src) {
1243
+ try {
1244
+ const pos = this.#parsed.positionAt(startIndex);
1245
+ const result = (0, import_babel.parseExpression)(src, {
1246
+ plugins,
1247
+ startIndex,
1248
+ startLine: pos.line + 1,
1249
+ startColumn: pos.character,
1250
+ strictMode: true,
1251
+ errorRecovery: true,
1252
+ sourceType: "module",
1253
+ allowUndeclaredExports: true,
1254
+ allowSuperOutsideMethod: true,
1255
+ allowAwaitOutsideFunction: true,
1256
+ allowReturnOutsideFunction: true,
1257
+ sourceFilename: this.#parsed.filename
1258
+ });
1259
+ this.#cache.set(startIndex, result);
1260
+ return result;
1261
+ } catch {
1262
+ this.#cache.set(startIndex, false);
1263
+ }
1264
+ }
1265
+ };
1266
+
1079
1267
  // src/extractors/script/util/attach-scopes.ts
1080
1268
  var VISITOR_KEYS = import_compiler.types.VISITOR_KEYS;
1081
- var ATTR_UNAMED = "value";
1269
+ var ATTR_UNNAMED = "value";
1082
1270
  var Scopes = /* @__PURE__ */ new WeakMap();
1083
1271
  var BoundAttrValueRange = /* @__PURE__ */ new WeakMap();
1084
- function crawlProgramScope(parsed, scriptParser) {
1272
+ function crawlProgramScope(parsed, ast) {
1085
1273
  var _a;
1086
- const { program, read } = parsed;
1274
+ const { program } = parsed;
1087
1275
  const mutations = [];
1088
1276
  const potentialHoists = [];
1089
- const nodesToCheckForMutations = /* @__PURE__ */ new Map();
1277
+ const potentialMutations = /* @__PURE__ */ new Map();
1090
1278
  const programScope = {
1091
1279
  parent: void 0,
1092
1280
  hoists: false,
@@ -1134,10 +1322,13 @@ function crawlProgramScope(parsed, scriptParser) {
1134
1322
  }
1135
1323
  }
1136
1324
  }
1137
- for (const [scope, nodes] of nodesToCheckForMutations) {
1325
+ for (const [scope, nodes] of potentialMutations) {
1326
+ const shadows = /* @__PURE__ */ new Set();
1327
+ const blockMutations = [];
1138
1328
  for (const node of nodes) {
1139
- trackMutationsInClosures(node, scope, mutations);
1329
+ trackMutations(node, scope, mutations, shadows, blockMutations);
1140
1330
  }
1331
+ flushMutations(scope, mutations, shadows, blockMutations);
1141
1332
  }
1142
1333
  if (mutations.length) {
1143
1334
  return mutations.sort(byStart);
@@ -1150,18 +1341,14 @@ function crawlProgramScope(parsed, scriptParser) {
1150
1341
  case 16 /* AttrTag */: {
1151
1342
  if (child.var) {
1152
1343
  parentScope.bindings ??= {};
1153
- const parsedFn = scriptParser.expressionAt(
1154
- child.var.value.start - 1,
1155
- `(${read(child.var.value)})=>0`
1156
- );
1157
- if (parsedFn) {
1158
- const lVal = parsedFn.params[0];
1159
- checkForMutations(parentScope, lVal);
1344
+ const tagVar = ast.tagVar(child.var);
1345
+ if (tagVar) {
1346
+ checkForMutations(parentScope, tagVar);
1160
1347
  for (const id of getVarIdentifiers(
1161
1348
  parsed,
1162
- lVal,
1349
+ tagVar,
1163
1350
  "",
1164
- ATTR_UNAMED
1351
+ ATTR_UNNAMED
1165
1352
  )) {
1166
1353
  const { name, objectPath, sourceName } = id;
1167
1354
  const binding = parentScope.bindings[name] = {
@@ -1186,12 +1373,9 @@ function crawlProgramScope(parsed, scriptParser) {
1186
1373
  };
1187
1374
  if (child.params) {
1188
1375
  bodyScope.bindings ??= {};
1189
- const parsedFn = scriptParser.expressionAt(
1190
- child.params.start,
1191
- `(${read(child.params.value)})=>{}`
1192
- );
1193
- if (parsedFn) {
1194
- for (const param of parsedFn.params) {
1376
+ const parsedParams = ast.tagParams(child.params);
1377
+ if (parsedParams) {
1378
+ for (const param of parsedParams) {
1195
1379
  checkForMutations(bodyScope, param);
1196
1380
  for (const name of getIdentifiers(param)) {
1197
1381
  bodyScope.bindings[name] = {
@@ -1205,19 +1389,16 @@ function crawlProgramScope(parsed, scriptParser) {
1205
1389
  }
1206
1390
  }
1207
1391
  }
1208
- if (isTextOnlyScript(child)) {
1209
- checkForMutations(
1210
- parentScope,
1211
- scriptParser.expressionAt(
1212
- child.body[0].start - "async ()=>{\n".length,
1213
- `async ()=>{
1214
- ${read({
1215
- start: child.body[0].start,
1216
- end: child.body[child.body.length - 1].end
1217
- })}
1218
- }`
1219
- )
1220
- );
1392
+ const scriptBody = ast.scriptBody(child);
1393
+ if (scriptBody) {
1394
+ const nodes = potentialMutations.get(parentScope);
1395
+ if (nodes) {
1396
+ nodes.push(...scriptBody);
1397
+ } else {
1398
+ potentialMutations.set(parentScope, [
1399
+ ...scriptBody
1400
+ ]);
1401
+ }
1221
1402
  } else {
1222
1403
  visit(child.body, bodyScope);
1223
1404
  }
@@ -1227,22 +1408,13 @@ ${read({
1227
1408
  for (const attr of child.attrs) {
1228
1409
  switch (attr.type) {
1229
1410
  case 15 /* AttrSpread */: {
1230
- checkForMutations(
1231
- parentScope,
1232
- scriptParser.expressionAt(
1233
- attr.value.start,
1234
- read(attr.value)
1235
- )
1236
- );
1411
+ checkForMutations(parentScope, ast.attrSpread(attr));
1237
1412
  break;
1238
1413
  }
1239
1414
  case 10 /* AttrNamed */: {
1240
1415
  switch ((_a2 = attr.value) == null ? void 0 : _a2.type) {
1241
1416
  case 13 /* AttrValue */: {
1242
- let parsedValue = scriptParser.expressionAt(
1243
- attr.value.value.start,
1244
- read(attr.value.value)
1245
- );
1417
+ let parsedValue = ast.attrValue(attr.value);
1246
1418
  if (parsedValue) {
1247
1419
  if (!attr.value.bound) {
1248
1420
  checkForMutations(parentScope, parsedValue);
@@ -1292,13 +1464,7 @@ ${read({
1292
1464
  case 14 /* AttrMethod */: {
1293
1465
  checkForMutations(
1294
1466
  parentScope,
1295
- scriptParser.expressionAt(
1296
- attr.value.params.start - 2,
1297
- `{_${read({
1298
- start: attr.value.params.start,
1299
- end: attr.value.body.end
1300
- })}}`
1301
- )
1467
+ ast.attrMethod(attr.value)
1302
1468
  );
1303
1469
  break;
1304
1470
  }
@@ -1315,12 +1481,24 @@ ${read({
1315
1481
  }
1316
1482
  function checkForMutations(scope, node) {
1317
1483
  if (node) {
1318
- const nodes = nodesToCheckForMutations.get(scope);
1319
- if (nodes) {
1320
- nodes.push(node);
1321
- } else {
1322
- nodesToCheckForMutations.set(scope, [node]);
1323
- }
1484
+ traverse(node, (child) => {
1485
+ switch (child.type) {
1486
+ case "FunctionDeclaration":
1487
+ case "FunctionExpression":
1488
+ case "ObjectMethod":
1489
+ case "ArrowFunctionExpression":
1490
+ case "ClassMethod":
1491
+ case "ClassPrivateMethod": {
1492
+ const nodes = potentialMutations.get(scope);
1493
+ if (nodes) {
1494
+ nodes.push(child);
1495
+ } else {
1496
+ potentialMutations.set(scope, [child]);
1497
+ }
1498
+ return true;
1499
+ }
1500
+ }
1501
+ });
1324
1502
  }
1325
1503
  }
1326
1504
  }
@@ -1499,32 +1677,13 @@ function* getVarIdentifiers(parsed, lVal, objectPath, sourceName) {
1499
1677
  break;
1500
1678
  }
1501
1679
  }
1502
- function trackMutationsInClosures(root, scope, mutations) {
1503
- traverse(root, (node) => {
1504
- switch (node.type) {
1505
- // Since the root will always be an expression it's impossible
1506
- // to hit a "FunctionDeclaration" without first going through
1507
- // a a different function context. So we don't need to track it.
1508
- // case "FunctionDeclaration":
1509
- case "FunctionExpression":
1510
- case "ObjectMethod":
1511
- case "ArrowFunctionExpression":
1512
- case "ClassMethod":
1513
- case "ClassPrivateMethod":
1514
- trackMutations(node, scope, mutations, node, /* @__PURE__ */ new Set(), []);
1515
- return true;
1516
- }
1517
- });
1518
- }
1519
- function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows, parentBlockMutations) {
1680
+ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockMutations) {
1520
1681
  if (!node) return;
1521
- let block = parentBlock;
1522
1682
  let blockShadows = parentBlockShadows;
1523
1683
  let blockMutations = parentBlockMutations;
1524
1684
  switch (node.type) {
1525
1685
  case "BlockStatement":
1526
- if (block !== node) {
1527
- block = node;
1686
+ if (blockMutations === parentBlockMutations) {
1528
1687
  blockShadows = new Set(blockShadows);
1529
1688
  blockMutations = [];
1530
1689
  }
@@ -1532,12 +1691,10 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1532
1691
  case "ForStatement":
1533
1692
  case "ForInStatement":
1534
1693
  case "ForOfStatement":
1535
- block = node.body;
1536
1694
  blockShadows = new Set(blockShadows);
1537
1695
  blockMutations = [];
1538
1696
  break;
1539
1697
  case "ArrowFunctionExpression":
1540
- block = node.body;
1541
1698
  blockShadows = new Set(blockShadows);
1542
1699
  blockMutations = [];
1543
1700
  for (const param of node.params) {
@@ -1547,7 +1704,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1547
1704
  case "ObjectMethod":
1548
1705
  case "ClassMethod":
1549
1706
  case "ClassPrivateMethod":
1550
- block = node.body;
1551
1707
  blockShadows = new Set(blockShadows);
1552
1708
  blockMutations = [];
1553
1709
  for (const param of node.params) {
@@ -1555,7 +1711,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1555
1711
  }
1556
1712
  break;
1557
1713
  case "FunctionExpression":
1558
- block = node.body;
1559
1714
  blockShadows = new Set(blockShadows);
1560
1715
  blockMutations = [];
1561
1716
  if (node.id) {
@@ -1567,7 +1722,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1567
1722
  break;
1568
1723
  case "FunctionDeclaration":
1569
1724
  trackShadows(node.id, scope, parentBlockShadows);
1570
- block = node.body;
1571
1725
  blockShadows = new Set(blockShadows);
1572
1726
  blockMutations = [];
1573
1727
  for (const param of node.params) {
@@ -1575,7 +1729,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1575
1729
  }
1576
1730
  break;
1577
1731
  case "ClassExpression":
1578
- block = node.body;
1579
1732
  blockShadows = new Set(blockShadows);
1580
1733
  blockMutations = [];
1581
1734
  if (node.id) {
@@ -1586,12 +1739,10 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1586
1739
  if (node.id) {
1587
1740
  trackShadows(node.id, scope, parentBlockShadows);
1588
1741
  }
1589
- block = node.body;
1590
1742
  blockShadows = new Set(blockShadows);
1591
1743
  blockMutations = [];
1592
1744
  break;
1593
1745
  case "CatchClause":
1594
- block = node.body;
1595
1746
  blockShadows = new Set(blockShadows);
1596
1747
  blockMutations = [];
1597
1748
  if (node.param) {
@@ -1618,34 +1769,23 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1618
1769
  const child = node[key];
1619
1770
  if (Array.isArray(child)) {
1620
1771
  for (const item of child) {
1621
- trackMutations(
1622
- item,
1623
- scope,
1624
- mutations,
1625
- block,
1626
- blockShadows,
1627
- blockMutations
1628
- );
1772
+ trackMutations(item, scope, mutations, blockShadows, blockMutations);
1629
1773
  }
1630
1774
  } else {
1631
- trackMutations(
1632
- child,
1633
- scope,
1634
- mutations,
1635
- block,
1636
- blockShadows,
1637
- blockMutations
1638
- );
1775
+ trackMutations(child, scope, mutations, blockShadows, blockMutations);
1639
1776
  }
1640
1777
  }
1641
- if (block !== parentBlock && blockMutations.length) {
1642
- for (const { name, start } of blockMutations) {
1643
- if (start == null || blockShadows.has(name)) continue;
1644
- const binding = resolveWritableVar(scope, name);
1645
- if (binding) {
1646
- binding.mutated = true;
1647
- mutations.push({ start, binding });
1648
- }
1778
+ if (blockMutations !== parentBlockMutations && blockMutations.length) {
1779
+ flushMutations(scope, mutations, blockShadows, blockMutations);
1780
+ }
1781
+ }
1782
+ function flushMutations(scope, mutations, blockShadows, blockMutations) {
1783
+ for (const { name, start } of blockMutations) {
1784
+ if (start == null || blockShadows.has(name)) continue;
1785
+ const binding = resolveWritableVar(scope, name);
1786
+ if (binding) {
1787
+ binding.mutated = true;
1788
+ mutations.push({ start, binding });
1649
1789
  }
1650
1790
  }
1651
1791
  }
@@ -1941,58 +2081,6 @@ function getRuntimeOverrides(api, runtimeTypes, generics, applyGenerics, returnT
1941
2081
  return result;
1942
2082
  }
1943
2083
 
1944
- // src/extractors/script/util/script-parser.ts
1945
- var import_babel = require("@marko/compiler/internal/babel");
1946
- var plugins = ["exportDefaultFrom", "importAssertions", "typescript"];
1947
- var ScriptParser = class {
1948
- #parsed;
1949
- constructor(parsed) {
1950
- this.#parsed = parsed;
1951
- }
1952
- statementAt(startIndex, src) {
1953
- const pos = this.#parsed.positionAt(startIndex);
1954
- try {
1955
- return (0, import_babel.parse)(src, {
1956
- plugins,
1957
- startIndex,
1958
- startLine: pos.line + 1,
1959
- startColumn: pos.character,
1960
- strictMode: true,
1961
- errorRecovery: true,
1962
- sourceType: "module",
1963
- allowUndeclaredExports: true,
1964
- allowSuperOutsideMethod: true,
1965
- allowAwaitOutsideFunction: true,
1966
- allowReturnOutsideFunction: true,
1967
- sourceFilename: this.#parsed.filename
1968
- }).program.body;
1969
- } catch {
1970
- return [];
1971
- }
1972
- }
1973
- expressionAt(startIndex, src) {
1974
- const pos = this.#parsed.positionAt(startIndex);
1975
- try {
1976
- return (0, import_babel.parseExpression)(src, {
1977
- plugins,
1978
- startIndex,
1979
- startLine: pos.line + 1,
1980
- startColumn: pos.character,
1981
- strictMode: true,
1982
- errorRecovery: true,
1983
- sourceType: "module",
1984
- allowUndeclaredExports: true,
1985
- allowSuperOutsideMethod: true,
1986
- allowAwaitOutsideFunction: true,
1987
- allowReturnOutsideFunction: true,
1988
- sourceFilename: this.#parsed.filename
1989
- });
1990
- } catch {
1991
- return;
1992
- }
1993
- }
1994
- };
1995
-
1996
2084
  // src/extractors/script/index.ts
1997
2085
  var SEP_EMPTY = "";
1998
2086
  var SEP_SPACE = " ";
@@ -2000,7 +2088,7 @@ var SEP_COMMA_SPACE = ", ";
2000
2088
  var SEP_COMMA_NEW_LINE = ",\n";
2001
2089
  var VAR_LOCAL_PREFIX = "__marko_internal_";
2002
2090
  var VAR_SHARED_PREFIX = `Marko._.`;
2003
- var ATTR_UNAMED2 = "value";
2091
+ var ATTR_UNNAMED2 = "value";
2004
2092
  var REG_EXT = /(?<=[/\\][^/\\]+)\.[^.]+$/;
2005
2093
  var REG_BLOCK = /\s*{/y;
2006
2094
  var REG_NEW_LINE = /^|(\r?\n)/g;
@@ -2031,7 +2119,7 @@ var ScriptExtractor = class {
2031
2119
  #interop;
2032
2120
  #parsed;
2033
2121
  #extractor;
2034
- #scriptParser;
2122
+ #ast;
2035
2123
  #read;
2036
2124
  #lookup;
2037
2125
  #scriptLang;
@@ -2057,9 +2145,9 @@ var ScriptExtractor = class {
2057
2145
  this.#ts = opts.ts;
2058
2146
  this.#runtimeTypes = opts.runtimeTypesCode;
2059
2147
  this.#extractor = new Extractor(parsed);
2060
- this.#scriptParser = new ScriptParser(parsed);
2148
+ this.#ast = new ScriptParser(parsed);
2061
2149
  this.#read = parsed.read.bind(parsed);
2062
- this.#mutations = crawlProgramScope(this.#parsed, this.#scriptParser);
2150
+ this.#mutations = crawlProgramScope(this.#parsed, this.#ast);
2063
2151
  this.#writeProgram(parsed.program);
2064
2152
  }
2065
2153
  end() {
@@ -2359,8 +2447,10 @@ function ${templateName}() {
2359
2447
  this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2360
2448
  `);
2361
2449
  if (scopeExpr) {
2362
- this.#extractor.write(`[${varShared("scope")}] = ${scopeExpr};
2363
- `);
2450
+ this.#extractor.write(
2451
+ `readonly [${varShared("scope")}] = ${scopeExpr};
2452
+ `
2453
+ );
2364
2454
  }
2365
2455
  this.#extractor.write(`declare return: Return;
2366
2456
  constructor(_?: Return) {}
@@ -2404,7 +2494,7 @@ constructor(_?: Return) {}
2404
2494
  }
2405
2495
  this.#writeComments(child);
2406
2496
  this.#extractor.write("if (").copy(
2407
- this.#getRangeWithoutTrailingComma((_a = child.args) == null ? void 0 : _a.value) || this.#getAttrValue(child, ATTR_UNAMED2) || "undefined"
2497
+ this.#getRangeWithoutTrailingComma((_a = child.args) == null ? void 0 : _a.value) || this.#getAttrValue(child, ATTR_UNNAMED2) || "undefined"
2408
2498
  ).write(") {\n");
2409
2499
  const ifBody = this.#processBody(child);
2410
2500
  if (ifBody == null ? void 0 : ifBody.content) {
@@ -2684,7 +2774,7 @@ scope: ${scopeExpr}
2684
2774
  const value = attr.value;
2685
2775
  const modifier = !value || value.type === 13 /* AttrValue */ ? this.#getNamedAttrModifier(attr) : void 0;
2686
2776
  const defaultMapPosition = isDefault ? attr.name : void 0;
2687
- let name = isDefault ? ATTR_UNAMED2 : attr.name;
2777
+ let name = isDefault ? ATTR_UNNAMED2 : attr.name;
2688
2778
  if (modifier) {
2689
2779
  name = { start: attr.name.start, end: modifier.start - 1 };
2690
2780
  }
@@ -2761,10 +2851,10 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2761
2851
  stringLiteralFirstArgMatch[2]
2762
2852
  );
2763
2853
  if (isValidProperty) {
2764
- const propertNameStart = stringLiteralStart + 1;
2854
+ const propertyNameStart = stringLiteralStart + 1;
2765
2855
  this.#extractor.write("component.").copy({
2766
- start: propertNameStart,
2767
- end: propertNameStart + stringLiteralValue.length
2856
+ start: propertyNameStart,
2857
+ end: propertyNameStart + stringLiteralValue.length
2768
2858
  });
2769
2859
  } else {
2770
2860
  this.#extractor.write(`component[`).copy({
@@ -2800,7 +2890,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2800
2890
  );
2801
2891
  return hasAttrs;
2802
2892
  }
2803
- #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }) {
2893
+ #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }, constraintExpr) {
2804
2894
  let wasMerge = false;
2805
2895
  if (dynamicAttrTagParents) {
2806
2896
  if (staticAttrTags) {
@@ -2821,7 +2911,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2821
2911
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2822
2912
  }
2823
2913
  if (dynamicAttrTagParents) {
2824
- this.#writeDynamicAttrTagParents(dynamicAttrTagParents);
2914
+ this.#writeDynamicAttrTagParents(dynamicAttrTagParents, constraintExpr);
2825
2915
  if (wasMerge) this.#extractor.write(`)${SEP_COMMA_NEW_LINE}`);
2826
2916
  }
2827
2917
  }
@@ -2837,18 +2927,8 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2837
2927
  if (isRepeated) {
2838
2928
  const templateVar = this.#getTemplateVar(firstAttrTag.owner);
2839
2929
  if (templateVar) {
2840
- let accessor = `"${name}"`;
2841
- let curTag = firstAttrTag.parent;
2842
- while (curTag) {
2843
- if (curTag.type === 16 /* AttrTag */) {
2844
- accessor = `"${this.#getAttrTagName(curTag)}",${accessor}`;
2845
- } else if (!isControlFlowTag(curTag)) {
2846
- break;
2847
- }
2848
- curTag = curTag.parent;
2849
- }
2850
2930
  this.#extractor.write(
2851
- `${varShared("attrTagFor")}(${templateVar},${accessor})(`
2931
+ `${varShared("attrTagFor")}(${templateVar},${this.#getAttrTagPath(firstAttrTag)})(`
2852
2932
  );
2853
2933
  } else {
2854
2934
  this.#extractor.write(`${varShared("attrTag")}(`);
@@ -2870,7 +2950,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2870
2950
  }
2871
2951
  }
2872
2952
  }
2873
- #writeDynamicAttrTagParents(dynamicAttrTagParents) {
2953
+ #writeDynamicAttrTagParents(dynamicAttrTagParents, constraintExpr) {
2874
2954
  var _a, _b, _c;
2875
2955
  for (const tag of dynamicAttrTagParents) {
2876
2956
  switch (tag.nameText) {
@@ -2878,7 +2958,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2878
2958
  const alternates = IF_TAG_ALTERNATES.get(tag);
2879
2959
  this.#writeComments(tag);
2880
2960
  this.#extractor.write("((\n").copy(
2881
- this.#getRangeWithoutTrailingComma((_a = tag.args) == null ? void 0 : _a.value) || this.#getAttrValue(tag, ATTR_UNAMED2) || "undefined"
2961
+ this.#getRangeWithoutTrailingComma((_a = tag.args) == null ? void 0 : _a.value) || this.#getAttrValue(tag, ATTR_UNNAMED2) || "undefined"
2882
2962
  ).write("\n) ? ");
2883
2963
  this.#writeDynamicAttrTagBody(tag);
2884
2964
  let needsAlternate = true;
@@ -2912,8 +2992,12 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2912
2992
  this.#extractor.write("\n}, \n");
2913
2993
  this.#writeComments(tag);
2914
2994
  this.#extractor.copy(tag.typeParams).write("(\n").copy((_b = tag.params) == null ? void 0 : _b.value).write("\n) => (");
2915
- this.#writeDynamicAttrTagBody(tag);
2916
- this.#extractor.write("))");
2995
+ this.#writeDynamicAttrTagBody(tag, constraintExpr);
2996
+ this.#extractor.write(")");
2997
+ if (constraintExpr) {
2998
+ this.#extractor.write(`,${constraintExpr}`);
2999
+ }
3000
+ this.#extractor.write(")");
2917
3001
  break;
2918
3002
  }
2919
3003
  case "while": {
@@ -2971,7 +3055,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2971
3055
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2972
3056
  } else if (body) {
2973
3057
  hasInput = true;
2974
- this.#writeAttrTags(body);
3058
+ this.#writeAttrTags(body, this.#getTagInputType(tag));
2975
3059
  hasBodyContent = body.content !== void 0;
2976
3060
  } else if (tag.close) {
2977
3061
  hasBodyContent = true;
@@ -3134,7 +3218,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3134
3218
  const alternate = {
3135
3219
  condition: this.#getRangeWithoutTrailingComma(
3136
3220
  (_a = nextChild.args) == null ? void 0 : _a.value
3137
- ) || this.#getAttrValue(nextChild, ATTR_UNAMED2),
3221
+ ) || this.#getAttrValue(nextChild, ATTR_UNNAMED2),
3138
3222
  node: nextChild
3139
3223
  };
3140
3224
  hasDynamicAttrTags ||= nextChild.hasAttrTags;
@@ -3207,7 +3291,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3207
3291
  return { content, staticAttrTags, dynamicAttrTagParents };
3208
3292
  }
3209
3293
  }
3210
- #writeDynamicAttrTagBody(tag) {
3294
+ #writeDynamicAttrTagBody(tag, constraintExpr) {
3211
3295
  const body = this.#processBody(tag);
3212
3296
  if (body) {
3213
3297
  if (body.content) {
@@ -3216,7 +3300,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3216
3300
  this.#extractor.write("return ");
3217
3301
  }
3218
3302
  this.#extractor.write("{\n");
3219
- this.#writeAttrTags(body);
3303
+ this.#writeAttrTags(body, constraintExpr);
3220
3304
  this.#extractor.write("}");
3221
3305
  if (body.content) {
3222
3306
  this.#endChildren();
@@ -3229,7 +3313,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3229
3313
  #getAttrValue(tag, name) {
3230
3314
  if (tag.attrs) {
3231
3315
  for (const attr of tag.attrs) {
3232
- if (isValueAttribute(attr) && (this.#read(attr.name) || ATTR_UNAMED2) === name) {
3316
+ if (isValueAttribute(attr) && (this.#read(attr.name) || ATTR_UNNAMED2) === name) {
3233
3317
  return attr.value.value;
3234
3318
  }
3235
3319
  }
@@ -3267,9 +3351,9 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3267
3351
  var _a;
3268
3352
  for (const node of program.static) {
3269
3353
  if (node.type === 25 /* Export */) {
3270
- const start = node.start + "export ".length;
3271
- if (this.#testAtIndex(REG_INPUT_TYPE, start)) {
3272
- const [inputType] = this.#scriptParser.statementAt(start, this.#read({ start, end: node.end }));
3354
+ if (this.#testAtIndex(REG_INPUT_TYPE, node.start + "export ".length)) {
3355
+ const exported = this.#ast.export(node);
3356
+ const inputType = exported == null ? void 0 : exported.declaration;
3273
3357
  return {
3274
3358
  typeParameters: (_a = inputType == null ? void 0 : inputType.typeParameters) == null ? void 0 : _a.params.map((param) => {
3275
3359
  return {
@@ -3376,6 +3460,30 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3376
3460
  const { nameText } = tag;
3377
3461
  return ((_a = this.#lookup.getTag(nameText)) == null ? void 0 : _a.targetProperty) || nameText.slice(nameText.lastIndexOf(":") + 1);
3378
3462
  }
3463
+ #getAttrTagPath(tag) {
3464
+ let path4 = `"${this.#getAttrTagName(tag)}"`;
3465
+ let curTag = tag.parent;
3466
+ while (curTag) {
3467
+ if (curTag.type === 16 /* AttrTag */) {
3468
+ path4 = `"${this.#getAttrTagName(curTag)}",${path4}`;
3469
+ } else if (!isControlFlowTag(curTag)) {
3470
+ break;
3471
+ }
3472
+ curTag = curTag.parent;
3473
+ }
3474
+ return path4;
3475
+ }
3476
+ #getTagInputType(tag) {
3477
+ if (tag.type === 16 /* AttrTag */) {
3478
+ if (!tag.owner) return;
3479
+ const templateVar2 = this.#getTemplateVar(tag.owner);
3480
+ if (!templateVar2) return;
3481
+ return `${varShared("inputForAttr")}(${templateVar2},${this.#getAttrTagPath(tag)})`;
3482
+ }
3483
+ const templateVar = this.#getTemplateVar(tag);
3484
+ if (!templateVar) return;
3485
+ return `${varShared("input")}(${templateVar})`;
3486
+ }
3379
3487
  #writeAttrTagTree(tree, valueExpression, nested) {
3380
3488
  this.#extractor.write(
3381
3489
  `${varShared(nested ? "nestedAttrTagNames" : "attrTagNames")}(${valueExpression},input=>{
@@ -3965,7 +4073,7 @@ var marko_default = {
3965
4073
  isExportComponentType(statement) || // skips the generated `export { type Component }`.
3966
4074
  isImportComponentType(statement) || // skips the generated `import type Component from "..."`.
3967
4075
  isExportEmptyInputType(statement) || // skips empty exported Input, eg `export type Input = {}` or `export interface Input {}`.
3968
- isExportInputTypeAsComponentInput(statement) || // skips outputing `export type Input = Component["input"]` since it's inferred.
4076
+ isExportInputTypeAsComponentInput(statement) || // skips outputting `export type Input = Component["input"]` since it's inferred.
3969
4077
  defaultExportId && // If the `export default` was an identifier, we also remove the variable that declared the identifier.
3970
4078
  isVariableStatementForName(statement, defaultExportId)) {
3971
4079
  continue;