@marko/language-tools 2.5.57 → 2.5.58

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
@@ -863,7 +863,10 @@ function sortBySourceThenGenerated(a, b) {
863
863
  }
864
864
 
865
865
  // 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)$/;
866
+ var builtinTagsRegex = (
867
+ /* cspell:disable-next-line */
868
+ /^(?: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)$/
869
+ );
867
870
  function isHTMLTag(tag) {
868
871
  return builtinTagsRegex.test(tag);
869
872
  }
@@ -1062,31 +1065,16 @@ var import_relative_import_path = require("relative-import-path");
1062
1065
 
1063
1066
  // src/extractors/script/util/attach-scopes.ts
1064
1067
  var import_compiler = require("@marko/compiler");
1065
-
1066
- // src/extractors/script/util/is-text-only-script.ts
1067
- function isTextOnlyScript(tag) {
1068
- if (tag.nameText !== "script" || tag.args || tag.attrs || !tag.body) {
1069
- return false;
1070
- }
1071
- for (const child of tag.body) {
1072
- if (child.type !== 17 /* Text */) {
1073
- return false;
1074
- }
1075
- }
1076
- return true;
1077
- }
1078
-
1079
- // src/extractors/script/util/attach-scopes.ts
1080
1068
  var VISITOR_KEYS = import_compiler.types.VISITOR_KEYS;
1081
- var ATTR_UNAMED = "value";
1069
+ var ATTR_UNNAMED = "value";
1082
1070
  var Scopes = /* @__PURE__ */ new WeakMap();
1083
1071
  var BoundAttrValueRange = /* @__PURE__ */ new WeakMap();
1084
- function crawlProgramScope(parsed, scriptParser) {
1072
+ function crawlProgramScope(parsed, ast) {
1085
1073
  var _a;
1086
- const { program, read } = parsed;
1074
+ const { program } = parsed;
1087
1075
  const mutations = [];
1088
1076
  const potentialHoists = [];
1089
- const nodesToCheckForMutations = /* @__PURE__ */ new Map();
1077
+ const potentialMutations = /* @__PURE__ */ new Map();
1090
1078
  const programScope = {
1091
1079
  parent: void 0,
1092
1080
  hoists: false,
@@ -1134,10 +1122,13 @@ function crawlProgramScope(parsed, scriptParser) {
1134
1122
  }
1135
1123
  }
1136
1124
  }
1137
- for (const [scope, nodes] of nodesToCheckForMutations) {
1125
+ for (const [scope, nodes] of potentialMutations) {
1126
+ const shadows = /* @__PURE__ */ new Set();
1127
+ const blockMutations = [];
1138
1128
  for (const node of nodes) {
1139
- trackMutationsInClosures(node, scope, mutations);
1129
+ trackMutations(node, scope, mutations, shadows, blockMutations);
1140
1130
  }
1131
+ flushMutations(scope, mutations, shadows, blockMutations);
1141
1132
  }
1142
1133
  if (mutations.length) {
1143
1134
  return mutations.sort(byStart);
@@ -1150,18 +1141,14 @@ function crawlProgramScope(parsed, scriptParser) {
1150
1141
  case 16 /* AttrTag */: {
1151
1142
  if (child.var) {
1152
1143
  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);
1144
+ const tagVar = ast.tagVar(child.var);
1145
+ if (tagVar) {
1146
+ checkForMutations(parentScope, tagVar);
1160
1147
  for (const id of getVarIdentifiers(
1161
1148
  parsed,
1162
- lVal,
1149
+ tagVar,
1163
1150
  "",
1164
- ATTR_UNAMED
1151
+ ATTR_UNNAMED
1165
1152
  )) {
1166
1153
  const { name, objectPath, sourceName } = id;
1167
1154
  const binding = parentScope.bindings[name] = {
@@ -1186,12 +1173,9 @@ function crawlProgramScope(parsed, scriptParser) {
1186
1173
  };
1187
1174
  if (child.params) {
1188
1175
  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) {
1176
+ const parsedParams = ast.tagParams(child.params);
1177
+ if (parsedParams) {
1178
+ for (const param of parsedParams) {
1195
1179
  checkForMutations(bodyScope, param);
1196
1180
  for (const name of getIdentifiers(param)) {
1197
1181
  bodyScope.bindings[name] = {
@@ -1205,19 +1189,16 @@ function crawlProgramScope(parsed, scriptParser) {
1205
1189
  }
1206
1190
  }
1207
1191
  }
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
- );
1192
+ const scriptBody = ast.scriptBody(child);
1193
+ if (scriptBody) {
1194
+ const nodes = potentialMutations.get(parentScope);
1195
+ if (nodes) {
1196
+ nodes.push(...scriptBody);
1197
+ } else {
1198
+ potentialMutations.set(parentScope, [
1199
+ ...scriptBody
1200
+ ]);
1201
+ }
1221
1202
  } else {
1222
1203
  visit(child.body, bodyScope);
1223
1204
  }
@@ -1227,22 +1208,13 @@ ${read({
1227
1208
  for (const attr of child.attrs) {
1228
1209
  switch (attr.type) {
1229
1210
  case 15 /* AttrSpread */: {
1230
- checkForMutations(
1231
- parentScope,
1232
- scriptParser.expressionAt(
1233
- attr.value.start,
1234
- read(attr.value)
1235
- )
1236
- );
1211
+ checkForMutations(parentScope, ast.attrSpread(attr));
1237
1212
  break;
1238
1213
  }
1239
1214
  case 10 /* AttrNamed */: {
1240
1215
  switch ((_a2 = attr.value) == null ? void 0 : _a2.type) {
1241
1216
  case 13 /* AttrValue */: {
1242
- let parsedValue = scriptParser.expressionAt(
1243
- attr.value.value.start,
1244
- read(attr.value.value)
1245
- );
1217
+ let parsedValue = ast.attrValue(attr.value);
1246
1218
  if (parsedValue) {
1247
1219
  if (!attr.value.bound) {
1248
1220
  checkForMutations(parentScope, parsedValue);
@@ -1292,13 +1264,7 @@ ${read({
1292
1264
  case 14 /* AttrMethod */: {
1293
1265
  checkForMutations(
1294
1266
  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
- )
1267
+ ast.attrMethod(attr.value)
1302
1268
  );
1303
1269
  break;
1304
1270
  }
@@ -1315,12 +1281,24 @@ ${read({
1315
1281
  }
1316
1282
  function checkForMutations(scope, node) {
1317
1283
  if (node) {
1318
- const nodes = nodesToCheckForMutations.get(scope);
1319
- if (nodes) {
1320
- nodes.push(node);
1321
- } else {
1322
- nodesToCheckForMutations.set(scope, [node]);
1323
- }
1284
+ traverse(node, (child) => {
1285
+ switch (child.type) {
1286
+ case "FunctionDeclaration":
1287
+ case "FunctionExpression":
1288
+ case "ObjectMethod":
1289
+ case "ArrowFunctionExpression":
1290
+ case "ClassMethod":
1291
+ case "ClassPrivateMethod": {
1292
+ const nodes = potentialMutations.get(scope);
1293
+ if (nodes) {
1294
+ nodes.push(child);
1295
+ } else {
1296
+ potentialMutations.set(scope, [child]);
1297
+ }
1298
+ return true;
1299
+ }
1300
+ }
1301
+ });
1324
1302
  }
1325
1303
  }
1326
1304
  }
@@ -1499,32 +1477,13 @@ function* getVarIdentifiers(parsed, lVal, objectPath, sourceName) {
1499
1477
  break;
1500
1478
  }
1501
1479
  }
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) {
1480
+ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockMutations) {
1520
1481
  if (!node) return;
1521
- let block = parentBlock;
1522
1482
  let blockShadows = parentBlockShadows;
1523
1483
  let blockMutations = parentBlockMutations;
1524
1484
  switch (node.type) {
1525
1485
  case "BlockStatement":
1526
- if (block !== node) {
1527
- block = node;
1486
+ if (blockMutations === parentBlockMutations) {
1528
1487
  blockShadows = new Set(blockShadows);
1529
1488
  blockMutations = [];
1530
1489
  }
@@ -1532,12 +1491,10 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1532
1491
  case "ForStatement":
1533
1492
  case "ForInStatement":
1534
1493
  case "ForOfStatement":
1535
- block = node.body;
1536
1494
  blockShadows = new Set(blockShadows);
1537
1495
  blockMutations = [];
1538
1496
  break;
1539
1497
  case "ArrowFunctionExpression":
1540
- block = node.body;
1541
1498
  blockShadows = new Set(blockShadows);
1542
1499
  blockMutations = [];
1543
1500
  for (const param of node.params) {
@@ -1547,7 +1504,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1547
1504
  case "ObjectMethod":
1548
1505
  case "ClassMethod":
1549
1506
  case "ClassPrivateMethod":
1550
- block = node.body;
1551
1507
  blockShadows = new Set(blockShadows);
1552
1508
  blockMutations = [];
1553
1509
  for (const param of node.params) {
@@ -1555,7 +1511,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1555
1511
  }
1556
1512
  break;
1557
1513
  case "FunctionExpression":
1558
- block = node.body;
1559
1514
  blockShadows = new Set(blockShadows);
1560
1515
  blockMutations = [];
1561
1516
  if (node.id) {
@@ -1567,7 +1522,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1567
1522
  break;
1568
1523
  case "FunctionDeclaration":
1569
1524
  trackShadows(node.id, scope, parentBlockShadows);
1570
- block = node.body;
1571
1525
  blockShadows = new Set(blockShadows);
1572
1526
  blockMutations = [];
1573
1527
  for (const param of node.params) {
@@ -1575,7 +1529,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1575
1529
  }
1576
1530
  break;
1577
1531
  case "ClassExpression":
1578
- block = node.body;
1579
1532
  blockShadows = new Set(blockShadows);
1580
1533
  blockMutations = [];
1581
1534
  if (node.id) {
@@ -1586,12 +1539,10 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1586
1539
  if (node.id) {
1587
1540
  trackShadows(node.id, scope, parentBlockShadows);
1588
1541
  }
1589
- block = node.body;
1590
1542
  blockShadows = new Set(blockShadows);
1591
1543
  blockMutations = [];
1592
1544
  break;
1593
1545
  case "CatchClause":
1594
- block = node.body;
1595
1546
  blockShadows = new Set(blockShadows);
1596
1547
  blockMutations = [];
1597
1548
  if (node.param) {
@@ -1618,34 +1569,23 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1618
1569
  const child = node[key];
1619
1570
  if (Array.isArray(child)) {
1620
1571
  for (const item of child) {
1621
- trackMutations(
1622
- item,
1623
- scope,
1624
- mutations,
1625
- block,
1626
- blockShadows,
1627
- blockMutations
1628
- );
1572
+ trackMutations(item, scope, mutations, blockShadows, blockMutations);
1629
1573
  }
1630
1574
  } else {
1631
- trackMutations(
1632
- child,
1633
- scope,
1634
- mutations,
1635
- block,
1636
- blockShadows,
1637
- blockMutations
1638
- );
1575
+ trackMutations(child, scope, mutations, blockShadows, blockMutations);
1639
1576
  }
1640
1577
  }
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
- }
1578
+ if (blockMutations !== parentBlockMutations && blockMutations.length) {
1579
+ flushMutations(scope, mutations, blockShadows, blockMutations);
1580
+ }
1581
+ }
1582
+ function flushMutations(scope, mutations, blockShadows, blockMutations) {
1583
+ for (const { name, start } of blockMutations) {
1584
+ if (start == null || blockShadows.has(name)) continue;
1585
+ const binding = resolveWritableVar(scope, name);
1586
+ if (binding) {
1587
+ binding.mutated = true;
1588
+ mutations.push({ start, binding });
1649
1589
  }
1650
1590
  }
1651
1591
  }
@@ -1832,6 +1772,19 @@ function detectAPIFromTag(parsed, tag) {
1832
1772
  return detectAPIFromBody(parsed, tag.body);
1833
1773
  }
1834
1774
 
1775
+ // src/extractors/script/util/is-text-only-script.ts
1776
+ function isTextOnlyScript(tag) {
1777
+ if (tag.nameText !== "script" || tag.args || tag.attrs || !tag.body) {
1778
+ return false;
1779
+ }
1780
+ for (const child of tag.body) {
1781
+ if (child.type !== 17 /* Text */) {
1782
+ return false;
1783
+ }
1784
+ }
1785
+ return true;
1786
+ }
1787
+
1835
1788
  // src/extractors/script/util/jsdoc-input-type.ts
1836
1789
  var MaybeInputTypedefReg = /@typedef\b[\s\S]*\bInput\b/;
1837
1790
  function getJSDocInputType(comment, ts) {
@@ -1946,13 +1899,137 @@ var import_babel = require("@marko/compiler/internal/babel");
1946
1899
  var plugins = ["exportDefaultFrom", "importAssertions", "typescript"];
1947
1900
  var ScriptParser = class {
1948
1901
  #parsed;
1902
+ #cache = /* @__PURE__ */ new Map();
1949
1903
  constructor(parsed) {
1950
1904
  this.#parsed = parsed;
1951
1905
  }
1952
- statementAt(startIndex, src) {
1953
- const pos = this.#parsed.positionAt(startIndex);
1906
+ tagName(name) {
1907
+ return this.#templateExpressions(name);
1908
+ }
1909
+ tagShorthandId(shorthandId) {
1910
+ return this.#templateExpressions(shorthandId);
1911
+ }
1912
+ tagShorthandClassName(node) {
1913
+ return this.#templateExpressions(node);
1914
+ }
1915
+ tagVar(node) {
1916
+ const start = node.value.start - 1;
1917
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `(${this.#parsed.read(node.value)})=>0`);
1918
+ if (expr) {
1919
+ return expr.params[0];
1920
+ }
1921
+ }
1922
+ tagParams(node) {
1923
+ const start = node.start;
1924
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `(${this.#parsed.read(node.value)})=>0`);
1925
+ if (expr) {
1926
+ return expr.params;
1927
+ }
1928
+ }
1929
+ tagTypeParams(node) {
1930
+ const start = node.value.start - 1;
1931
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `<${this.#parsed.read(node.value)}>()=>0`);
1932
+ if (expr) {
1933
+ return expr.typeParameters;
1934
+ }
1935
+ }
1936
+ tagArgs(node) {
1937
+ const start = node.value.start - 2;
1938
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `_(${this.#parsed.read(node.value)})`);
1939
+ if (expr) {
1940
+ return expr.arguments;
1941
+ }
1942
+ }
1943
+ tagTypeArgs(node) {
1944
+ const start = node.value.start - 2;
1945
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `_<${this.#parsed.read(node.value)}>()`);
1946
+ if (expr) {
1947
+ return expr.typeParameters;
1948
+ }
1949
+ }
1950
+ attrValue(node) {
1951
+ const start = node.value.start;
1952
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1953
+ }
1954
+ attrSpread(node) {
1955
+ const start = node.value.start;
1956
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1957
+ }
1958
+ attrMethod(node) {
1959
+ const start = node.params.start - 2;
1960
+ const expr = this.#cache.get(start) ?? this.#expressionAt(
1961
+ start,
1962
+ `{_${this.#parsed.read({ start: node.params.start, end: node.body.end })}}`
1963
+ );
1964
+ if (expr) {
1965
+ return expr.properties[0];
1966
+ }
1967
+ }
1968
+ attrArgs(node) {
1969
+ const start = node.value.start;
1970
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1971
+ }
1972
+ placeholder(node) {
1973
+ const start = node.value.start;
1974
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1975
+ }
1976
+ scriptBody(node) {
1977
+ if (!isTextOnlyScript(node)) return;
1978
+ const start = node.body[0].start;
1979
+ const statements = this.#cache.get(start) ?? this.#statementsAt(
1980
+ start,
1981
+ this.#parsed.read({ start, end: node.body[node.body.length - 1].end })
1982
+ );
1983
+ if (statements) {
1984
+ return statements;
1985
+ }
1986
+ }
1987
+ scriptlet(node) {
1988
+ const start = node.value.start;
1989
+ const statements = this.#cache.get(start) ?? this.#statementsAt(start, this.#parsed.read(node.value));
1990
+ if (statements) {
1991
+ return statements;
1992
+ }
1993
+ }
1994
+ import(node) {
1995
+ const statements = this.#cache.get(node.start) ?? this.#statementsAt(node.start, this.#parsed.read(node));
1996
+ if (statements) {
1997
+ return statements[0];
1998
+ }
1999
+ }
2000
+ export(node) {
2001
+ const statements = this.#cache.get(node.start) ?? this.#statementsAt(node.start, this.#parsed.read(node));
2002
+ if (statements) {
2003
+ return statements[0];
2004
+ }
2005
+ }
2006
+ class(node) {
2007
+ const expr = this.#cache.get(node.start) ?? this.#expressionAt(node.start, this.#parsed.read(node));
2008
+ return expr || void 0;
2009
+ }
2010
+ static(node) {
2011
+ const start = node.start + "static ".length;
2012
+ const statements = this.#cache.get(start) ?? this.#statementsAt(start, this.#parsed.read({ start, end: node.end }));
2013
+ if (statements) {
2014
+ return statements;
2015
+ }
2016
+ }
2017
+ #templateExpressions(template) {
2018
+ const { expressions } = template;
2019
+ if (!expressions.length) return;
2020
+ const result = [];
2021
+ for (const expr of expressions) {
2022
+ const start = expr.value.start;
2023
+ const parsed = this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(expr.value));
2024
+ if (!parsed) return;
2025
+ result.push(parsed);
2026
+ }
2027
+ if (result.length) return result;
2028
+ }
2029
+ #statementsAt(startIndex, src) {
1954
2030
  try {
1955
- return (0, import_babel.parse)(src, {
2031
+ const pos = this.#parsed.positionAt(startIndex);
2032
+ const result = (0, import_babel.parse)(src, {
1956
2033
  plugins,
1957
2034
  startIndex,
1958
2035
  startLine: pos.line + 1,
@@ -1966,14 +2043,18 @@ var ScriptParser = class {
1966
2043
  allowReturnOutsideFunction: true,
1967
2044
  sourceFilename: this.#parsed.filename
1968
2045
  }).program.body;
2046
+ if (result.length) {
2047
+ this.#cache.set(startIndex, result);
2048
+ return result;
2049
+ }
1969
2050
  } catch {
1970
- return [];
1971
2051
  }
2052
+ this.#cache.set(startIndex, false);
1972
2053
  }
1973
- expressionAt(startIndex, src) {
1974
- const pos = this.#parsed.positionAt(startIndex);
2054
+ #expressionAt(startIndex, src) {
1975
2055
  try {
1976
- return (0, import_babel.parseExpression)(src, {
2056
+ const pos = this.#parsed.positionAt(startIndex);
2057
+ const result = (0, import_babel.parseExpression)(src, {
1977
2058
  plugins,
1978
2059
  startIndex,
1979
2060
  startLine: pos.line + 1,
@@ -1987,8 +2068,10 @@ var ScriptParser = class {
1987
2068
  allowReturnOutsideFunction: true,
1988
2069
  sourceFilename: this.#parsed.filename
1989
2070
  });
2071
+ this.#cache.set(startIndex, result);
2072
+ return result;
1990
2073
  } catch {
1991
- return;
2074
+ this.#cache.set(startIndex, false);
1992
2075
  }
1993
2076
  }
1994
2077
  };
@@ -2000,7 +2083,7 @@ var SEP_COMMA_SPACE = ", ";
2000
2083
  var SEP_COMMA_NEW_LINE = ",\n";
2001
2084
  var VAR_LOCAL_PREFIX = "__marko_internal_";
2002
2085
  var VAR_SHARED_PREFIX = `Marko._.`;
2003
- var ATTR_UNAMED2 = "value";
2086
+ var ATTR_UNNAMED2 = "value";
2004
2087
  var REG_EXT = /(?<=[/\\][^/\\]+)\.[^.]+$/;
2005
2088
  var REG_BLOCK = /\s*{/y;
2006
2089
  var REG_NEW_LINE = /^|(\r?\n)/g;
@@ -2031,7 +2114,7 @@ var ScriptExtractor = class {
2031
2114
  #interop;
2032
2115
  #parsed;
2033
2116
  #extractor;
2034
- #scriptParser;
2117
+ #ast;
2035
2118
  #read;
2036
2119
  #lookup;
2037
2120
  #scriptLang;
@@ -2057,9 +2140,9 @@ var ScriptExtractor = class {
2057
2140
  this.#ts = opts.ts;
2058
2141
  this.#runtimeTypes = opts.runtimeTypesCode;
2059
2142
  this.#extractor = new Extractor(parsed);
2060
- this.#scriptParser = new ScriptParser(parsed);
2143
+ this.#ast = new ScriptParser(parsed);
2061
2144
  this.#read = parsed.read.bind(parsed);
2062
- this.#mutations = crawlProgramScope(this.#parsed, this.#scriptParser);
2145
+ this.#mutations = crawlProgramScope(this.#parsed, this.#ast);
2063
2146
  this.#writeProgram(parsed.program);
2064
2147
  }
2065
2148
  end() {
@@ -2359,8 +2442,10 @@ function ${templateName}() {
2359
2442
  this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2360
2443
  `);
2361
2444
  if (scopeExpr) {
2362
- this.#extractor.write(`[${varShared("scope")}] = ${scopeExpr};
2363
- `);
2445
+ this.#extractor.write(
2446
+ `readonly [${varShared("scope")}] = ${scopeExpr};
2447
+ `
2448
+ );
2364
2449
  }
2365
2450
  this.#extractor.write(`declare return: Return;
2366
2451
  constructor(_?: Return) {}
@@ -2404,7 +2489,7 @@ constructor(_?: Return) {}
2404
2489
  }
2405
2490
  this.#writeComments(child);
2406
2491
  this.#extractor.write("if (").copy(
2407
- this.#getRangeWithoutTrailingComma((_a = child.args) == null ? void 0 : _a.value) || this.#getAttrValue(child, ATTR_UNAMED2) || "undefined"
2492
+ this.#getRangeWithoutTrailingComma((_a = child.args) == null ? void 0 : _a.value) || this.#getAttrValue(child, ATTR_UNNAMED2) || "undefined"
2408
2493
  ).write(") {\n");
2409
2494
  const ifBody = this.#processBody(child);
2410
2495
  if (ifBody == null ? void 0 : ifBody.content) {
@@ -2684,7 +2769,7 @@ scope: ${scopeExpr}
2684
2769
  const value = attr.value;
2685
2770
  const modifier = !value || value.type === 13 /* AttrValue */ ? this.#getNamedAttrModifier(attr) : void 0;
2686
2771
  const defaultMapPosition = isDefault ? attr.name : void 0;
2687
- let name = isDefault ? ATTR_UNAMED2 : attr.name;
2772
+ let name = isDefault ? ATTR_UNNAMED2 : attr.name;
2688
2773
  if (modifier) {
2689
2774
  name = { start: attr.name.start, end: modifier.start - 1 };
2690
2775
  }
@@ -2761,10 +2846,10 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2761
2846
  stringLiteralFirstArgMatch[2]
2762
2847
  );
2763
2848
  if (isValidProperty) {
2764
- const propertNameStart = stringLiteralStart + 1;
2849
+ const propertyNameStart = stringLiteralStart + 1;
2765
2850
  this.#extractor.write("component.").copy({
2766
- start: propertNameStart,
2767
- end: propertNameStart + stringLiteralValue.length
2851
+ start: propertyNameStart,
2852
+ end: propertyNameStart + stringLiteralValue.length
2768
2853
  });
2769
2854
  } else {
2770
2855
  this.#extractor.write(`component[`).copy({
@@ -2800,7 +2885,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2800
2885
  );
2801
2886
  return hasAttrs;
2802
2887
  }
2803
- #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }) {
2888
+ #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }, constraintExpr) {
2804
2889
  let wasMerge = false;
2805
2890
  if (dynamicAttrTagParents) {
2806
2891
  if (staticAttrTags) {
@@ -2821,7 +2906,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2821
2906
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2822
2907
  }
2823
2908
  if (dynamicAttrTagParents) {
2824
- this.#writeDynamicAttrTagParents(dynamicAttrTagParents);
2909
+ this.#writeDynamicAttrTagParents(dynamicAttrTagParents, constraintExpr);
2825
2910
  if (wasMerge) this.#extractor.write(`)${SEP_COMMA_NEW_LINE}`);
2826
2911
  }
2827
2912
  }
@@ -2837,18 +2922,8 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2837
2922
  if (isRepeated) {
2838
2923
  const templateVar = this.#getTemplateVar(firstAttrTag.owner);
2839
2924
  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
2925
  this.#extractor.write(
2851
- `${varShared("attrTagFor")}(${templateVar},${accessor})(`
2926
+ `${varShared("attrTagFor")}(${templateVar},${this.#getAttrTagPath(firstAttrTag)})(`
2852
2927
  );
2853
2928
  } else {
2854
2929
  this.#extractor.write(`${varShared("attrTag")}(`);
@@ -2870,7 +2945,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2870
2945
  }
2871
2946
  }
2872
2947
  }
2873
- #writeDynamicAttrTagParents(dynamicAttrTagParents) {
2948
+ #writeDynamicAttrTagParents(dynamicAttrTagParents, constraintExpr) {
2874
2949
  var _a, _b, _c;
2875
2950
  for (const tag of dynamicAttrTagParents) {
2876
2951
  switch (tag.nameText) {
@@ -2878,7 +2953,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2878
2953
  const alternates = IF_TAG_ALTERNATES.get(tag);
2879
2954
  this.#writeComments(tag);
2880
2955
  this.#extractor.write("((\n").copy(
2881
- this.#getRangeWithoutTrailingComma((_a = tag.args) == null ? void 0 : _a.value) || this.#getAttrValue(tag, ATTR_UNAMED2) || "undefined"
2956
+ this.#getRangeWithoutTrailingComma((_a = tag.args) == null ? void 0 : _a.value) || this.#getAttrValue(tag, ATTR_UNNAMED2) || "undefined"
2882
2957
  ).write("\n) ? ");
2883
2958
  this.#writeDynamicAttrTagBody(tag);
2884
2959
  let needsAlternate = true;
@@ -2912,8 +2987,12 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2912
2987
  this.#extractor.write("\n}, \n");
2913
2988
  this.#writeComments(tag);
2914
2989
  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("))");
2990
+ this.#writeDynamicAttrTagBody(tag, constraintExpr);
2991
+ this.#extractor.write(")");
2992
+ if (constraintExpr) {
2993
+ this.#extractor.write(`,${constraintExpr}`);
2994
+ }
2995
+ this.#extractor.write(")");
2917
2996
  break;
2918
2997
  }
2919
2998
  case "while": {
@@ -2971,7 +3050,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2971
3050
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2972
3051
  } else if (body) {
2973
3052
  hasInput = true;
2974
- this.#writeAttrTags(body);
3053
+ this.#writeAttrTags(body, this.#getTagInputType(tag));
2975
3054
  hasBodyContent = body.content !== void 0;
2976
3055
  } else if (tag.close) {
2977
3056
  hasBodyContent = true;
@@ -3134,7 +3213,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3134
3213
  const alternate = {
3135
3214
  condition: this.#getRangeWithoutTrailingComma(
3136
3215
  (_a = nextChild.args) == null ? void 0 : _a.value
3137
- ) || this.#getAttrValue(nextChild, ATTR_UNAMED2),
3216
+ ) || this.#getAttrValue(nextChild, ATTR_UNNAMED2),
3138
3217
  node: nextChild
3139
3218
  };
3140
3219
  hasDynamicAttrTags ||= nextChild.hasAttrTags;
@@ -3207,7 +3286,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3207
3286
  return { content, staticAttrTags, dynamicAttrTagParents };
3208
3287
  }
3209
3288
  }
3210
- #writeDynamicAttrTagBody(tag) {
3289
+ #writeDynamicAttrTagBody(tag, constraintExpr) {
3211
3290
  const body = this.#processBody(tag);
3212
3291
  if (body) {
3213
3292
  if (body.content) {
@@ -3216,7 +3295,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3216
3295
  this.#extractor.write("return ");
3217
3296
  }
3218
3297
  this.#extractor.write("{\n");
3219
- this.#writeAttrTags(body);
3298
+ this.#writeAttrTags(body, constraintExpr);
3220
3299
  this.#extractor.write("}");
3221
3300
  if (body.content) {
3222
3301
  this.#endChildren();
@@ -3229,7 +3308,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3229
3308
  #getAttrValue(tag, name) {
3230
3309
  if (tag.attrs) {
3231
3310
  for (const attr of tag.attrs) {
3232
- if (isValueAttribute(attr) && (this.#read(attr.name) || ATTR_UNAMED2) === name) {
3311
+ if (isValueAttribute(attr) && (this.#read(attr.name) || ATTR_UNNAMED2) === name) {
3233
3312
  return attr.value.value;
3234
3313
  }
3235
3314
  }
@@ -3267,9 +3346,9 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3267
3346
  var _a;
3268
3347
  for (const node of program.static) {
3269
3348
  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 }));
3349
+ if (this.#testAtIndex(REG_INPUT_TYPE, node.start + "export ".length)) {
3350
+ const exported = this.#ast.export(node);
3351
+ const inputType = exported == null ? void 0 : exported.declaration;
3273
3352
  return {
3274
3353
  typeParameters: (_a = inputType == null ? void 0 : inputType.typeParameters) == null ? void 0 : _a.params.map((param) => {
3275
3354
  return {
@@ -3376,6 +3455,30 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3376
3455
  const { nameText } = tag;
3377
3456
  return ((_a = this.#lookup.getTag(nameText)) == null ? void 0 : _a.targetProperty) || nameText.slice(nameText.lastIndexOf(":") + 1);
3378
3457
  }
3458
+ #getAttrTagPath(tag) {
3459
+ let path4 = `"${this.#getAttrTagName(tag)}"`;
3460
+ let curTag = tag.parent;
3461
+ while (curTag) {
3462
+ if (curTag.type === 16 /* AttrTag */) {
3463
+ path4 = `"${this.#getAttrTagName(curTag)}",${path4}`;
3464
+ } else if (!isControlFlowTag(curTag)) {
3465
+ break;
3466
+ }
3467
+ curTag = curTag.parent;
3468
+ }
3469
+ return path4;
3470
+ }
3471
+ #getTagInputType(tag) {
3472
+ if (tag.type === 16 /* AttrTag */) {
3473
+ if (!tag.owner) return;
3474
+ const templateVar2 = this.#getTemplateVar(tag.owner);
3475
+ if (!templateVar2) return;
3476
+ return `${varShared("inputForAttr")}(${templateVar2},${this.#getAttrTagPath(tag)})`;
3477
+ }
3478
+ const templateVar = this.#getTemplateVar(tag);
3479
+ if (!templateVar) return;
3480
+ return `${varShared("input")}(${templateVar})`;
3481
+ }
3379
3482
  #writeAttrTagTree(tree, valueExpression, nested) {
3380
3483
  this.#extractor.write(
3381
3484
  `${varShared(nested ? "nestedAttrTagNames" : "attrTagNames")}(${valueExpression},input=>{
@@ -3965,7 +4068,7 @@ var marko_default = {
3965
4068
  isExportComponentType(statement) || // skips the generated `export { type Component }`.
3966
4069
  isImportComponentType(statement) || // skips the generated `import type Component from "..."`.
3967
4070
  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.
4071
+ isExportInputTypeAsComponentInput(statement) || // skips outputting `export type Input = Component["input"]` since it's inferred.
3969
4072
  defaultExportId && // If the `export default` was an identifier, we also remove the variable that declared the identifier.
3970
4073
  isVariableStatementForName(statement, defaultExportId)) {
3971
4074
  continue;