@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.mjs CHANGED
@@ -690,6 +690,7 @@ var Extracted = class {
690
690
  );
691
691
  }
692
692
  }
693
+ parsed;
693
694
  #generated;
694
695
  #sourceToGenerated;
695
696
  #generatedToSource;
@@ -823,7 +824,10 @@ function sortBySourceThenGenerated(a, b) {
823
824
  }
824
825
 
825
826
  // src/extractors/html/keywords.ts
826
- 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)$/;
827
+ var builtinTagsRegex = (
828
+ /* cspell:disable-next-line */
829
+ /^(?: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)$/
830
+ );
827
831
  function isHTMLTag(tag) {
828
832
  return builtinTagsRegex.test(tag);
829
833
  }
@@ -1023,6 +1027,12 @@ import { relativeImportPath } from "relative-import-path";
1023
1027
  // src/extractors/script/util/attach-scopes.ts
1024
1028
  import { types as t } from "@marko/compiler";
1025
1029
 
1030
+ // src/extractors/script/util/script-parser.ts
1031
+ import {
1032
+ parse as parseStatement,
1033
+ parseExpression
1034
+ } from "@marko/compiler/internal/babel";
1035
+
1026
1036
  // src/extractors/script/util/is-text-only-script.ts
1027
1037
  function isTextOnlyScript(tag) {
1028
1038
  if (tag.nameText !== "script" || tag.args || tag.attrs || !tag.body) {
@@ -1036,17 +1046,198 @@ function isTextOnlyScript(tag) {
1036
1046
  return true;
1037
1047
  }
1038
1048
 
1049
+ // src/extractors/script/util/script-parser.ts
1050
+ var plugins = ["exportDefaultFrom", "importAssertions", "typescript"];
1051
+ var ScriptParser = class {
1052
+ #parsed;
1053
+ #cache = /* @__PURE__ */ new Map();
1054
+ constructor(parsed) {
1055
+ this.#parsed = parsed;
1056
+ }
1057
+ tagName(name) {
1058
+ return this.#templateExpressions(name);
1059
+ }
1060
+ tagShorthandId(shorthandId) {
1061
+ return this.#templateExpressions(shorthandId);
1062
+ }
1063
+ tagShorthandClassName(node) {
1064
+ return this.#templateExpressions(node);
1065
+ }
1066
+ tagVar(node) {
1067
+ const start = node.value.start - 1;
1068
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `(${this.#parsed.read(node.value)})=>0`);
1069
+ if (expr) {
1070
+ return expr.params[0];
1071
+ }
1072
+ }
1073
+ tagParams(node) {
1074
+ const start = node.start;
1075
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `(${this.#parsed.read(node.value)})=>0`);
1076
+ if (expr) {
1077
+ return expr.params;
1078
+ }
1079
+ }
1080
+ tagTypeParams(node) {
1081
+ const start = node.value.start - 1;
1082
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `<${this.#parsed.read(node.value)}>()=>0`);
1083
+ if (expr) {
1084
+ return expr.typeParameters;
1085
+ }
1086
+ }
1087
+ tagArgs(node) {
1088
+ const start = node.value.start - 2;
1089
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `_(${this.#parsed.read(node.value)})`);
1090
+ if (expr) {
1091
+ return expr.arguments;
1092
+ }
1093
+ }
1094
+ tagTypeArgs(node) {
1095
+ const start = node.value.start - 2;
1096
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `_<${this.#parsed.read(node.value)}>()`);
1097
+ if (expr) {
1098
+ return expr.typeParameters;
1099
+ }
1100
+ }
1101
+ attrValue(node) {
1102
+ const start = node.value.start;
1103
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1104
+ }
1105
+ attrSpread(node) {
1106
+ const start = node.value.start;
1107
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1108
+ }
1109
+ attrMethod(node) {
1110
+ const start = node.params.start - 2;
1111
+ const expr = this.#cache.get(start) ?? this.#expressionAt(
1112
+ start,
1113
+ `{_${this.#parsed.read({ start: node.params.start, end: node.body.end })}}`
1114
+ );
1115
+ if (expr) {
1116
+ return expr.properties[0];
1117
+ }
1118
+ }
1119
+ attrArgs(node) {
1120
+ const start = node.value.start;
1121
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1122
+ }
1123
+ placeholder(node) {
1124
+ const start = node.value.start;
1125
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1126
+ }
1127
+ scriptBody(node) {
1128
+ if (!isTextOnlyScript(node)) return;
1129
+ const start = node.body[0].start;
1130
+ const statements = this.#cache.get(start) ?? this.#statementsAt(
1131
+ start,
1132
+ this.#parsed.read({ start, end: node.body[node.body.length - 1].end })
1133
+ );
1134
+ if (statements) {
1135
+ return statements;
1136
+ }
1137
+ }
1138
+ scriptlet(node) {
1139
+ const start = node.value.start;
1140
+ const statements = this.#cache.get(start) ?? this.#statementsAt(start, this.#parsed.read(node.value));
1141
+ if (statements) {
1142
+ return statements;
1143
+ }
1144
+ }
1145
+ import(node) {
1146
+ const statements = this.#cache.get(node.start) ?? this.#statementsAt(node.start, this.#parsed.read(node));
1147
+ if (statements) {
1148
+ return statements[0];
1149
+ }
1150
+ }
1151
+ export(node) {
1152
+ const statements = this.#cache.get(node.start) ?? this.#statementsAt(node.start, this.#parsed.read(node));
1153
+ if (statements) {
1154
+ return statements[0];
1155
+ }
1156
+ }
1157
+ class(node) {
1158
+ const expr = this.#cache.get(node.start) ?? this.#expressionAt(node.start, this.#parsed.read(node));
1159
+ return expr || void 0;
1160
+ }
1161
+ static(node) {
1162
+ const start = node.start + "static ".length;
1163
+ const statements = this.#cache.get(start) ?? this.#statementsAt(start, this.#parsed.read({ start, end: node.end }));
1164
+ if (statements) {
1165
+ return statements;
1166
+ }
1167
+ }
1168
+ #templateExpressions(template) {
1169
+ const { expressions } = template;
1170
+ if (!expressions.length) return;
1171
+ const result = [];
1172
+ for (const expr of expressions) {
1173
+ const start = expr.value.start;
1174
+ const parsed = this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(expr.value));
1175
+ if (!parsed) return;
1176
+ result.push(parsed);
1177
+ }
1178
+ if (result.length) return result;
1179
+ }
1180
+ #statementsAt(startIndex, src) {
1181
+ try {
1182
+ const pos = this.#parsed.positionAt(startIndex);
1183
+ const result = parseStatement(src, {
1184
+ plugins,
1185
+ startIndex,
1186
+ startLine: pos.line + 1,
1187
+ startColumn: pos.character,
1188
+ strictMode: true,
1189
+ errorRecovery: true,
1190
+ sourceType: "module",
1191
+ allowUndeclaredExports: true,
1192
+ allowSuperOutsideMethod: true,
1193
+ allowAwaitOutsideFunction: true,
1194
+ allowReturnOutsideFunction: true,
1195
+ sourceFilename: this.#parsed.filename
1196
+ }).program.body;
1197
+ if (result.length) {
1198
+ this.#cache.set(startIndex, result);
1199
+ return result;
1200
+ }
1201
+ } catch {
1202
+ }
1203
+ this.#cache.set(startIndex, false);
1204
+ }
1205
+ #expressionAt(startIndex, src) {
1206
+ try {
1207
+ const pos = this.#parsed.positionAt(startIndex);
1208
+ const result = parseExpression(src, {
1209
+ plugins,
1210
+ startIndex,
1211
+ startLine: pos.line + 1,
1212
+ startColumn: pos.character,
1213
+ strictMode: true,
1214
+ errorRecovery: true,
1215
+ sourceType: "module",
1216
+ allowUndeclaredExports: true,
1217
+ allowSuperOutsideMethod: true,
1218
+ allowAwaitOutsideFunction: true,
1219
+ allowReturnOutsideFunction: true,
1220
+ sourceFilename: this.#parsed.filename
1221
+ });
1222
+ this.#cache.set(startIndex, result);
1223
+ return result;
1224
+ } catch {
1225
+ this.#cache.set(startIndex, false);
1226
+ }
1227
+ }
1228
+ };
1229
+
1039
1230
  // src/extractors/script/util/attach-scopes.ts
1040
1231
  var VISITOR_KEYS = t.VISITOR_KEYS;
1041
- var ATTR_UNAMED = "value";
1232
+ var ATTR_UNNAMED = "value";
1042
1233
  var Scopes = /* @__PURE__ */ new WeakMap();
1043
1234
  var BoundAttrValueRange = /* @__PURE__ */ new WeakMap();
1044
- function crawlProgramScope(parsed, scriptParser) {
1235
+ function crawlProgramScope(parsed, ast) {
1045
1236
  var _a;
1046
- const { program, read } = parsed;
1237
+ const { program } = parsed;
1047
1238
  const mutations = [];
1048
1239
  const potentialHoists = [];
1049
- const nodesToCheckForMutations = /* @__PURE__ */ new Map();
1240
+ const potentialMutations = /* @__PURE__ */ new Map();
1050
1241
  const programScope = {
1051
1242
  parent: void 0,
1052
1243
  hoists: false,
@@ -1094,10 +1285,13 @@ function crawlProgramScope(parsed, scriptParser) {
1094
1285
  }
1095
1286
  }
1096
1287
  }
1097
- for (const [scope, nodes] of nodesToCheckForMutations) {
1288
+ for (const [scope, nodes] of potentialMutations) {
1289
+ const shadows = /* @__PURE__ */ new Set();
1290
+ const blockMutations = [];
1098
1291
  for (const node of nodes) {
1099
- trackMutationsInClosures(node, scope, mutations);
1292
+ trackMutations(node, scope, mutations, shadows, blockMutations);
1100
1293
  }
1294
+ flushMutations(scope, mutations, shadows, blockMutations);
1101
1295
  }
1102
1296
  if (mutations.length) {
1103
1297
  return mutations.sort(byStart);
@@ -1110,18 +1304,14 @@ function crawlProgramScope(parsed, scriptParser) {
1110
1304
  case 16 /* AttrTag */: {
1111
1305
  if (child.var) {
1112
1306
  parentScope.bindings ??= {};
1113
- const parsedFn = scriptParser.expressionAt(
1114
- child.var.value.start - 1,
1115
- `(${read(child.var.value)})=>0`
1116
- );
1117
- if (parsedFn) {
1118
- const lVal = parsedFn.params[0];
1119
- checkForMutations(parentScope, lVal);
1307
+ const tagVar = ast.tagVar(child.var);
1308
+ if (tagVar) {
1309
+ checkForMutations(parentScope, tagVar);
1120
1310
  for (const id of getVarIdentifiers(
1121
1311
  parsed,
1122
- lVal,
1312
+ tagVar,
1123
1313
  "",
1124
- ATTR_UNAMED
1314
+ ATTR_UNNAMED
1125
1315
  )) {
1126
1316
  const { name, objectPath, sourceName } = id;
1127
1317
  const binding = parentScope.bindings[name] = {
@@ -1146,12 +1336,9 @@ function crawlProgramScope(parsed, scriptParser) {
1146
1336
  };
1147
1337
  if (child.params) {
1148
1338
  bodyScope.bindings ??= {};
1149
- const parsedFn = scriptParser.expressionAt(
1150
- child.params.start,
1151
- `(${read(child.params.value)})=>{}`
1152
- );
1153
- if (parsedFn) {
1154
- for (const param of parsedFn.params) {
1339
+ const parsedParams = ast.tagParams(child.params);
1340
+ if (parsedParams) {
1341
+ for (const param of parsedParams) {
1155
1342
  checkForMutations(bodyScope, param);
1156
1343
  for (const name of getIdentifiers(param)) {
1157
1344
  bodyScope.bindings[name] = {
@@ -1165,19 +1352,16 @@ function crawlProgramScope(parsed, scriptParser) {
1165
1352
  }
1166
1353
  }
1167
1354
  }
1168
- if (isTextOnlyScript(child)) {
1169
- checkForMutations(
1170
- parentScope,
1171
- scriptParser.expressionAt(
1172
- child.body[0].start - "async ()=>{\n".length,
1173
- `async ()=>{
1174
- ${read({
1175
- start: child.body[0].start,
1176
- end: child.body[child.body.length - 1].end
1177
- })}
1178
- }`
1179
- )
1180
- );
1355
+ const scriptBody = ast.scriptBody(child);
1356
+ if (scriptBody) {
1357
+ const nodes = potentialMutations.get(parentScope);
1358
+ if (nodes) {
1359
+ nodes.push(...scriptBody);
1360
+ } else {
1361
+ potentialMutations.set(parentScope, [
1362
+ ...scriptBody
1363
+ ]);
1364
+ }
1181
1365
  } else {
1182
1366
  visit(child.body, bodyScope);
1183
1367
  }
@@ -1187,22 +1371,13 @@ ${read({
1187
1371
  for (const attr of child.attrs) {
1188
1372
  switch (attr.type) {
1189
1373
  case 15 /* AttrSpread */: {
1190
- checkForMutations(
1191
- parentScope,
1192
- scriptParser.expressionAt(
1193
- attr.value.start,
1194
- read(attr.value)
1195
- )
1196
- );
1374
+ checkForMutations(parentScope, ast.attrSpread(attr));
1197
1375
  break;
1198
1376
  }
1199
1377
  case 10 /* AttrNamed */: {
1200
1378
  switch ((_a2 = attr.value) == null ? void 0 : _a2.type) {
1201
1379
  case 13 /* AttrValue */: {
1202
- let parsedValue = scriptParser.expressionAt(
1203
- attr.value.value.start,
1204
- read(attr.value.value)
1205
- );
1380
+ let parsedValue = ast.attrValue(attr.value);
1206
1381
  if (parsedValue) {
1207
1382
  if (!attr.value.bound) {
1208
1383
  checkForMutations(parentScope, parsedValue);
@@ -1252,13 +1427,7 @@ ${read({
1252
1427
  case 14 /* AttrMethod */: {
1253
1428
  checkForMutations(
1254
1429
  parentScope,
1255
- scriptParser.expressionAt(
1256
- attr.value.params.start - 2,
1257
- `{_${read({
1258
- start: attr.value.params.start,
1259
- end: attr.value.body.end
1260
- })}}`
1261
- )
1430
+ ast.attrMethod(attr.value)
1262
1431
  );
1263
1432
  break;
1264
1433
  }
@@ -1275,12 +1444,24 @@ ${read({
1275
1444
  }
1276
1445
  function checkForMutations(scope, node) {
1277
1446
  if (node) {
1278
- const nodes = nodesToCheckForMutations.get(scope);
1279
- if (nodes) {
1280
- nodes.push(node);
1281
- } else {
1282
- nodesToCheckForMutations.set(scope, [node]);
1283
- }
1447
+ traverse(node, (child) => {
1448
+ switch (child.type) {
1449
+ case "FunctionDeclaration":
1450
+ case "FunctionExpression":
1451
+ case "ObjectMethod":
1452
+ case "ArrowFunctionExpression":
1453
+ case "ClassMethod":
1454
+ case "ClassPrivateMethod": {
1455
+ const nodes = potentialMutations.get(scope);
1456
+ if (nodes) {
1457
+ nodes.push(child);
1458
+ } else {
1459
+ potentialMutations.set(scope, [child]);
1460
+ }
1461
+ return true;
1462
+ }
1463
+ }
1464
+ });
1284
1465
  }
1285
1466
  }
1286
1467
  }
@@ -1459,32 +1640,13 @@ function* getVarIdentifiers(parsed, lVal, objectPath, sourceName) {
1459
1640
  break;
1460
1641
  }
1461
1642
  }
1462
- function trackMutationsInClosures(root, scope, mutations) {
1463
- traverse(root, (node) => {
1464
- switch (node.type) {
1465
- // Since the root will always be an expression it's impossible
1466
- // to hit a "FunctionDeclaration" without first going through
1467
- // a a different function context. So we don't need to track it.
1468
- // case "FunctionDeclaration":
1469
- case "FunctionExpression":
1470
- case "ObjectMethod":
1471
- case "ArrowFunctionExpression":
1472
- case "ClassMethod":
1473
- case "ClassPrivateMethod":
1474
- trackMutations(node, scope, mutations, node, /* @__PURE__ */ new Set(), []);
1475
- return true;
1476
- }
1477
- });
1478
- }
1479
- function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows, parentBlockMutations) {
1643
+ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockMutations) {
1480
1644
  if (!node) return;
1481
- let block = parentBlock;
1482
1645
  let blockShadows = parentBlockShadows;
1483
1646
  let blockMutations = parentBlockMutations;
1484
1647
  switch (node.type) {
1485
1648
  case "BlockStatement":
1486
- if (block !== node) {
1487
- block = node;
1649
+ if (blockMutations === parentBlockMutations) {
1488
1650
  blockShadows = new Set(blockShadows);
1489
1651
  blockMutations = [];
1490
1652
  }
@@ -1492,12 +1654,10 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1492
1654
  case "ForStatement":
1493
1655
  case "ForInStatement":
1494
1656
  case "ForOfStatement":
1495
- block = node.body;
1496
1657
  blockShadows = new Set(blockShadows);
1497
1658
  blockMutations = [];
1498
1659
  break;
1499
1660
  case "ArrowFunctionExpression":
1500
- block = node.body;
1501
1661
  blockShadows = new Set(blockShadows);
1502
1662
  blockMutations = [];
1503
1663
  for (const param of node.params) {
@@ -1507,7 +1667,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1507
1667
  case "ObjectMethod":
1508
1668
  case "ClassMethod":
1509
1669
  case "ClassPrivateMethod":
1510
- block = node.body;
1511
1670
  blockShadows = new Set(blockShadows);
1512
1671
  blockMutations = [];
1513
1672
  for (const param of node.params) {
@@ -1515,7 +1674,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1515
1674
  }
1516
1675
  break;
1517
1676
  case "FunctionExpression":
1518
- block = node.body;
1519
1677
  blockShadows = new Set(blockShadows);
1520
1678
  blockMutations = [];
1521
1679
  if (node.id) {
@@ -1527,7 +1685,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1527
1685
  break;
1528
1686
  case "FunctionDeclaration":
1529
1687
  trackShadows(node.id, scope, parentBlockShadows);
1530
- block = node.body;
1531
1688
  blockShadows = new Set(blockShadows);
1532
1689
  blockMutations = [];
1533
1690
  for (const param of node.params) {
@@ -1535,7 +1692,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1535
1692
  }
1536
1693
  break;
1537
1694
  case "ClassExpression":
1538
- block = node.body;
1539
1695
  blockShadows = new Set(blockShadows);
1540
1696
  blockMutations = [];
1541
1697
  if (node.id) {
@@ -1546,12 +1702,10 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1546
1702
  if (node.id) {
1547
1703
  trackShadows(node.id, scope, parentBlockShadows);
1548
1704
  }
1549
- block = node.body;
1550
1705
  blockShadows = new Set(blockShadows);
1551
1706
  blockMutations = [];
1552
1707
  break;
1553
1708
  case "CatchClause":
1554
- block = node.body;
1555
1709
  blockShadows = new Set(blockShadows);
1556
1710
  blockMutations = [];
1557
1711
  if (node.param) {
@@ -1578,34 +1732,23 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1578
1732
  const child = node[key];
1579
1733
  if (Array.isArray(child)) {
1580
1734
  for (const item of child) {
1581
- trackMutations(
1582
- item,
1583
- scope,
1584
- mutations,
1585
- block,
1586
- blockShadows,
1587
- blockMutations
1588
- );
1735
+ trackMutations(item, scope, mutations, blockShadows, blockMutations);
1589
1736
  }
1590
1737
  } else {
1591
- trackMutations(
1592
- child,
1593
- scope,
1594
- mutations,
1595
- block,
1596
- blockShadows,
1597
- blockMutations
1598
- );
1738
+ trackMutations(child, scope, mutations, blockShadows, blockMutations);
1599
1739
  }
1600
1740
  }
1601
- if (block !== parentBlock && blockMutations.length) {
1602
- for (const { name, start } of blockMutations) {
1603
- if (start == null || blockShadows.has(name)) continue;
1604
- const binding = resolveWritableVar(scope, name);
1605
- if (binding) {
1606
- binding.mutated = true;
1607
- mutations.push({ start, binding });
1608
- }
1741
+ if (blockMutations !== parentBlockMutations && blockMutations.length) {
1742
+ flushMutations(scope, mutations, blockShadows, blockMutations);
1743
+ }
1744
+ }
1745
+ function flushMutations(scope, mutations, blockShadows, blockMutations) {
1746
+ for (const { name, start } of blockMutations) {
1747
+ if (start == null || blockShadows.has(name)) continue;
1748
+ const binding = resolveWritableVar(scope, name);
1749
+ if (binding) {
1750
+ binding.mutated = true;
1751
+ mutations.push({ start, binding });
1609
1752
  }
1610
1753
  }
1611
1754
  }
@@ -1901,61 +2044,6 @@ function getRuntimeOverrides(api, runtimeTypes, generics, applyGenerics, returnT
1901
2044
  return result;
1902
2045
  }
1903
2046
 
1904
- // src/extractors/script/util/script-parser.ts
1905
- import {
1906
- parse as parseStatement,
1907
- parseExpression
1908
- } from "@marko/compiler/internal/babel";
1909
- var plugins = ["exportDefaultFrom", "importAssertions", "typescript"];
1910
- var ScriptParser = class {
1911
- #parsed;
1912
- constructor(parsed) {
1913
- this.#parsed = parsed;
1914
- }
1915
- statementAt(startIndex, src) {
1916
- const pos = this.#parsed.positionAt(startIndex);
1917
- try {
1918
- return parseStatement(src, {
1919
- plugins,
1920
- startIndex,
1921
- startLine: pos.line + 1,
1922
- startColumn: pos.character,
1923
- strictMode: true,
1924
- errorRecovery: true,
1925
- sourceType: "module",
1926
- allowUndeclaredExports: true,
1927
- allowSuperOutsideMethod: true,
1928
- allowAwaitOutsideFunction: true,
1929
- allowReturnOutsideFunction: true,
1930
- sourceFilename: this.#parsed.filename
1931
- }).program.body;
1932
- } catch {
1933
- return [];
1934
- }
1935
- }
1936
- expressionAt(startIndex, src) {
1937
- const pos = this.#parsed.positionAt(startIndex);
1938
- try {
1939
- return parseExpression(src, {
1940
- plugins,
1941
- startIndex,
1942
- startLine: pos.line + 1,
1943
- startColumn: pos.character,
1944
- strictMode: true,
1945
- errorRecovery: true,
1946
- sourceType: "module",
1947
- allowUndeclaredExports: true,
1948
- allowSuperOutsideMethod: true,
1949
- allowAwaitOutsideFunction: true,
1950
- allowReturnOutsideFunction: true,
1951
- sourceFilename: this.#parsed.filename
1952
- });
1953
- } catch {
1954
- return;
1955
- }
1956
- }
1957
- };
1958
-
1959
2047
  // src/extractors/script/index.ts
1960
2048
  var SEP_EMPTY = "";
1961
2049
  var SEP_SPACE = " ";
@@ -1963,7 +2051,7 @@ var SEP_COMMA_SPACE = ", ";
1963
2051
  var SEP_COMMA_NEW_LINE = ",\n";
1964
2052
  var VAR_LOCAL_PREFIX = "__marko_internal_";
1965
2053
  var VAR_SHARED_PREFIX = `Marko._.`;
1966
- var ATTR_UNAMED2 = "value";
2054
+ var ATTR_UNNAMED2 = "value";
1967
2055
  var REG_EXT = /(?<=[/\\][^/\\]+)\.[^.]+$/;
1968
2056
  var REG_BLOCK = /\s*{/y;
1969
2057
  var REG_NEW_LINE = /^|(\r?\n)/g;
@@ -1994,7 +2082,7 @@ var ScriptExtractor = class {
1994
2082
  #interop;
1995
2083
  #parsed;
1996
2084
  #extractor;
1997
- #scriptParser;
2085
+ #ast;
1998
2086
  #read;
1999
2087
  #lookup;
2000
2088
  #scriptLang;
@@ -2020,9 +2108,9 @@ var ScriptExtractor = class {
2020
2108
  this.#ts = opts.ts;
2021
2109
  this.#runtimeTypes = opts.runtimeTypesCode;
2022
2110
  this.#extractor = new Extractor(parsed);
2023
- this.#scriptParser = new ScriptParser(parsed);
2111
+ this.#ast = new ScriptParser(parsed);
2024
2112
  this.#read = parsed.read.bind(parsed);
2025
- this.#mutations = crawlProgramScope(this.#parsed, this.#scriptParser);
2113
+ this.#mutations = crawlProgramScope(this.#parsed, this.#ast);
2026
2114
  this.#writeProgram(parsed.program);
2027
2115
  }
2028
2116
  end() {
@@ -2322,8 +2410,10 @@ function ${templateName}() {
2322
2410
  this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2323
2411
  `);
2324
2412
  if (scopeExpr) {
2325
- this.#extractor.write(`[${varShared("scope")}] = ${scopeExpr};
2326
- `);
2413
+ this.#extractor.write(
2414
+ `readonly [${varShared("scope")}] = ${scopeExpr};
2415
+ `
2416
+ );
2327
2417
  }
2328
2418
  this.#extractor.write(`declare return: Return;
2329
2419
  constructor(_?: Return) {}
@@ -2367,7 +2457,7 @@ constructor(_?: Return) {}
2367
2457
  }
2368
2458
  this.#writeComments(child);
2369
2459
  this.#extractor.write("if (").copy(
2370
- this.#getRangeWithoutTrailingComma((_a = child.args) == null ? void 0 : _a.value) || this.#getAttrValue(child, ATTR_UNAMED2) || "undefined"
2460
+ this.#getRangeWithoutTrailingComma((_a = child.args) == null ? void 0 : _a.value) || this.#getAttrValue(child, ATTR_UNNAMED2) || "undefined"
2371
2461
  ).write(") {\n");
2372
2462
  const ifBody = this.#processBody(child);
2373
2463
  if (ifBody == null ? void 0 : ifBody.content) {
@@ -2647,7 +2737,7 @@ scope: ${scopeExpr}
2647
2737
  const value = attr.value;
2648
2738
  const modifier = !value || value.type === 13 /* AttrValue */ ? this.#getNamedAttrModifier(attr) : void 0;
2649
2739
  const defaultMapPosition = isDefault ? attr.name : void 0;
2650
- let name = isDefault ? ATTR_UNAMED2 : attr.name;
2740
+ let name = isDefault ? ATTR_UNNAMED2 : attr.name;
2651
2741
  if (modifier) {
2652
2742
  name = { start: attr.name.start, end: modifier.start - 1 };
2653
2743
  }
@@ -2724,10 +2814,10 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2724
2814
  stringLiteralFirstArgMatch[2]
2725
2815
  );
2726
2816
  if (isValidProperty) {
2727
- const propertNameStart = stringLiteralStart + 1;
2817
+ const propertyNameStart = stringLiteralStart + 1;
2728
2818
  this.#extractor.write("component.").copy({
2729
- start: propertNameStart,
2730
- end: propertNameStart + stringLiteralValue.length
2819
+ start: propertyNameStart,
2820
+ end: propertyNameStart + stringLiteralValue.length
2731
2821
  });
2732
2822
  } else {
2733
2823
  this.#extractor.write(`component[`).copy({
@@ -2763,7 +2853,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2763
2853
  );
2764
2854
  return hasAttrs;
2765
2855
  }
2766
- #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }) {
2856
+ #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }, constraintExpr) {
2767
2857
  let wasMerge = false;
2768
2858
  if (dynamicAttrTagParents) {
2769
2859
  if (staticAttrTags) {
@@ -2784,7 +2874,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2784
2874
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2785
2875
  }
2786
2876
  if (dynamicAttrTagParents) {
2787
- this.#writeDynamicAttrTagParents(dynamicAttrTagParents);
2877
+ this.#writeDynamicAttrTagParents(dynamicAttrTagParents, constraintExpr);
2788
2878
  if (wasMerge) this.#extractor.write(`)${SEP_COMMA_NEW_LINE}`);
2789
2879
  }
2790
2880
  }
@@ -2800,18 +2890,8 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2800
2890
  if (isRepeated) {
2801
2891
  const templateVar = this.#getTemplateVar(firstAttrTag.owner);
2802
2892
  if (templateVar) {
2803
- let accessor = `"${name}"`;
2804
- let curTag = firstAttrTag.parent;
2805
- while (curTag) {
2806
- if (curTag.type === 16 /* AttrTag */) {
2807
- accessor = `"${this.#getAttrTagName(curTag)}",${accessor}`;
2808
- } else if (!isControlFlowTag(curTag)) {
2809
- break;
2810
- }
2811
- curTag = curTag.parent;
2812
- }
2813
2893
  this.#extractor.write(
2814
- `${varShared("attrTagFor")}(${templateVar},${accessor})(`
2894
+ `${varShared("attrTagFor")}(${templateVar},${this.#getAttrTagPath(firstAttrTag)})(`
2815
2895
  );
2816
2896
  } else {
2817
2897
  this.#extractor.write(`${varShared("attrTag")}(`);
@@ -2833,7 +2913,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2833
2913
  }
2834
2914
  }
2835
2915
  }
2836
- #writeDynamicAttrTagParents(dynamicAttrTagParents) {
2916
+ #writeDynamicAttrTagParents(dynamicAttrTagParents, constraintExpr) {
2837
2917
  var _a, _b, _c;
2838
2918
  for (const tag of dynamicAttrTagParents) {
2839
2919
  switch (tag.nameText) {
@@ -2841,7 +2921,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2841
2921
  const alternates = IF_TAG_ALTERNATES.get(tag);
2842
2922
  this.#writeComments(tag);
2843
2923
  this.#extractor.write("((\n").copy(
2844
- this.#getRangeWithoutTrailingComma((_a = tag.args) == null ? void 0 : _a.value) || this.#getAttrValue(tag, ATTR_UNAMED2) || "undefined"
2924
+ this.#getRangeWithoutTrailingComma((_a = tag.args) == null ? void 0 : _a.value) || this.#getAttrValue(tag, ATTR_UNNAMED2) || "undefined"
2845
2925
  ).write("\n) ? ");
2846
2926
  this.#writeDynamicAttrTagBody(tag);
2847
2927
  let needsAlternate = true;
@@ -2875,8 +2955,12 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2875
2955
  this.#extractor.write("\n}, \n");
2876
2956
  this.#writeComments(tag);
2877
2957
  this.#extractor.copy(tag.typeParams).write("(\n").copy((_b = tag.params) == null ? void 0 : _b.value).write("\n) => (");
2878
- this.#writeDynamicAttrTagBody(tag);
2879
- this.#extractor.write("))");
2958
+ this.#writeDynamicAttrTagBody(tag, constraintExpr);
2959
+ this.#extractor.write(")");
2960
+ if (constraintExpr) {
2961
+ this.#extractor.write(`,${constraintExpr}`);
2962
+ }
2963
+ this.#extractor.write(")");
2880
2964
  break;
2881
2965
  }
2882
2966
  case "while": {
@@ -2934,7 +3018,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2934
3018
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2935
3019
  } else if (body) {
2936
3020
  hasInput = true;
2937
- this.#writeAttrTags(body);
3021
+ this.#writeAttrTags(body, this.#getTagInputType(tag));
2938
3022
  hasBodyContent = body.content !== void 0;
2939
3023
  } else if (tag.close) {
2940
3024
  hasBodyContent = true;
@@ -3097,7 +3181,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3097
3181
  const alternate = {
3098
3182
  condition: this.#getRangeWithoutTrailingComma(
3099
3183
  (_a = nextChild.args) == null ? void 0 : _a.value
3100
- ) || this.#getAttrValue(nextChild, ATTR_UNAMED2),
3184
+ ) || this.#getAttrValue(nextChild, ATTR_UNNAMED2),
3101
3185
  node: nextChild
3102
3186
  };
3103
3187
  hasDynamicAttrTags ||= nextChild.hasAttrTags;
@@ -3170,7 +3254,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3170
3254
  return { content, staticAttrTags, dynamicAttrTagParents };
3171
3255
  }
3172
3256
  }
3173
- #writeDynamicAttrTagBody(tag) {
3257
+ #writeDynamicAttrTagBody(tag, constraintExpr) {
3174
3258
  const body = this.#processBody(tag);
3175
3259
  if (body) {
3176
3260
  if (body.content) {
@@ -3179,7 +3263,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3179
3263
  this.#extractor.write("return ");
3180
3264
  }
3181
3265
  this.#extractor.write("{\n");
3182
- this.#writeAttrTags(body);
3266
+ this.#writeAttrTags(body, constraintExpr);
3183
3267
  this.#extractor.write("}");
3184
3268
  if (body.content) {
3185
3269
  this.#endChildren();
@@ -3192,7 +3276,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3192
3276
  #getAttrValue(tag, name) {
3193
3277
  if (tag.attrs) {
3194
3278
  for (const attr of tag.attrs) {
3195
- if (isValueAttribute(attr) && (this.#read(attr.name) || ATTR_UNAMED2) === name) {
3279
+ if (isValueAttribute(attr) && (this.#read(attr.name) || ATTR_UNNAMED2) === name) {
3196
3280
  return attr.value.value;
3197
3281
  }
3198
3282
  }
@@ -3230,9 +3314,9 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3230
3314
  var _a;
3231
3315
  for (const node of program.static) {
3232
3316
  if (node.type === 25 /* Export */) {
3233
- const start = node.start + "export ".length;
3234
- if (this.#testAtIndex(REG_INPUT_TYPE, start)) {
3235
- const [inputType] = this.#scriptParser.statementAt(start, this.#read({ start, end: node.end }));
3317
+ if (this.#testAtIndex(REG_INPUT_TYPE, node.start + "export ".length)) {
3318
+ const exported = this.#ast.export(node);
3319
+ const inputType = exported == null ? void 0 : exported.declaration;
3236
3320
  return {
3237
3321
  typeParameters: (_a = inputType == null ? void 0 : inputType.typeParameters) == null ? void 0 : _a.params.map((param) => {
3238
3322
  return {
@@ -3339,6 +3423,30 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3339
3423
  const { nameText } = tag;
3340
3424
  return ((_a = this.#lookup.getTag(nameText)) == null ? void 0 : _a.targetProperty) || nameText.slice(nameText.lastIndexOf(":") + 1);
3341
3425
  }
3426
+ #getAttrTagPath(tag) {
3427
+ let path4 = `"${this.#getAttrTagName(tag)}"`;
3428
+ let curTag = tag.parent;
3429
+ while (curTag) {
3430
+ if (curTag.type === 16 /* AttrTag */) {
3431
+ path4 = `"${this.#getAttrTagName(curTag)}",${path4}`;
3432
+ } else if (!isControlFlowTag(curTag)) {
3433
+ break;
3434
+ }
3435
+ curTag = curTag.parent;
3436
+ }
3437
+ return path4;
3438
+ }
3439
+ #getTagInputType(tag) {
3440
+ if (tag.type === 16 /* AttrTag */) {
3441
+ if (!tag.owner) return;
3442
+ const templateVar2 = this.#getTemplateVar(tag.owner);
3443
+ if (!templateVar2) return;
3444
+ return `${varShared("inputForAttr")}(${templateVar2},${this.#getAttrTagPath(tag)})`;
3445
+ }
3446
+ const templateVar = this.#getTemplateVar(tag);
3447
+ if (!templateVar) return;
3448
+ return `${varShared("input")}(${templateVar})`;
3449
+ }
3342
3450
  #writeAttrTagTree(tree, valueExpression, nested) {
3343
3451
  this.#extractor.write(
3344
3452
  `${varShared(nested ? "nestedAttrTagNames" : "attrTagNames")}(${valueExpression},input=>{
@@ -3928,7 +4036,7 @@ var marko_default = {
3928
4036
  isExportComponentType(statement) || // skips the generated `export { type Component }`.
3929
4037
  isImportComponentType(statement) || // skips the generated `import type Component from "..."`.
3930
4038
  isExportEmptyInputType(statement) || // skips empty exported Input, eg `export type Input = {}` or `export interface Input {}`.
3931
- isExportInputTypeAsComponentInput(statement) || // skips outputing `export type Input = Component["input"]` since it's inferred.
4039
+ isExportInputTypeAsComponentInput(statement) || // skips outputting `export type Input = Component["input"]` since it's inferred.
3932
4040
  defaultExportId && // If the `export default` was an identifier, we also remove the variable that declared the identifier.
3933
4041
  isVariableStatementForName(statement, defaultExportId)) {
3934
4042
  continue;