@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.mjs CHANGED
@@ -823,7 +823,10 @@ function sortBySourceThenGenerated(a, b) {
823
823
  }
824
824
 
825
825
  // 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)$/;
826
+ var builtinTagsRegex = (
827
+ /* cspell:disable-next-line */
828
+ /^(?: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)$/
829
+ );
827
830
  function isHTMLTag(tag) {
828
831
  return builtinTagsRegex.test(tag);
829
832
  }
@@ -1022,31 +1025,16 @@ import { relativeImportPath } from "relative-import-path";
1022
1025
 
1023
1026
  // src/extractors/script/util/attach-scopes.ts
1024
1027
  import { types as t } from "@marko/compiler";
1025
-
1026
- // src/extractors/script/util/is-text-only-script.ts
1027
- function isTextOnlyScript(tag) {
1028
- if (tag.nameText !== "script" || tag.args || tag.attrs || !tag.body) {
1029
- return false;
1030
- }
1031
- for (const child of tag.body) {
1032
- if (child.type !== 17 /* Text */) {
1033
- return false;
1034
- }
1035
- }
1036
- return true;
1037
- }
1038
-
1039
- // src/extractors/script/util/attach-scopes.ts
1040
1028
  var VISITOR_KEYS = t.VISITOR_KEYS;
1041
- var ATTR_UNAMED = "value";
1029
+ var ATTR_UNNAMED = "value";
1042
1030
  var Scopes = /* @__PURE__ */ new WeakMap();
1043
1031
  var BoundAttrValueRange = /* @__PURE__ */ new WeakMap();
1044
- function crawlProgramScope(parsed, scriptParser) {
1032
+ function crawlProgramScope(parsed, ast) {
1045
1033
  var _a;
1046
- const { program, read } = parsed;
1034
+ const { program } = parsed;
1047
1035
  const mutations = [];
1048
1036
  const potentialHoists = [];
1049
- const nodesToCheckForMutations = /* @__PURE__ */ new Map();
1037
+ const potentialMutations = /* @__PURE__ */ new Map();
1050
1038
  const programScope = {
1051
1039
  parent: void 0,
1052
1040
  hoists: false,
@@ -1094,10 +1082,13 @@ function crawlProgramScope(parsed, scriptParser) {
1094
1082
  }
1095
1083
  }
1096
1084
  }
1097
- for (const [scope, nodes] of nodesToCheckForMutations) {
1085
+ for (const [scope, nodes] of potentialMutations) {
1086
+ const shadows = /* @__PURE__ */ new Set();
1087
+ const blockMutations = [];
1098
1088
  for (const node of nodes) {
1099
- trackMutationsInClosures(node, scope, mutations);
1089
+ trackMutations(node, scope, mutations, shadows, blockMutations);
1100
1090
  }
1091
+ flushMutations(scope, mutations, shadows, blockMutations);
1101
1092
  }
1102
1093
  if (mutations.length) {
1103
1094
  return mutations.sort(byStart);
@@ -1110,18 +1101,14 @@ function crawlProgramScope(parsed, scriptParser) {
1110
1101
  case 16 /* AttrTag */: {
1111
1102
  if (child.var) {
1112
1103
  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);
1104
+ const tagVar = ast.tagVar(child.var);
1105
+ if (tagVar) {
1106
+ checkForMutations(parentScope, tagVar);
1120
1107
  for (const id of getVarIdentifiers(
1121
1108
  parsed,
1122
- lVal,
1109
+ tagVar,
1123
1110
  "",
1124
- ATTR_UNAMED
1111
+ ATTR_UNNAMED
1125
1112
  )) {
1126
1113
  const { name, objectPath, sourceName } = id;
1127
1114
  const binding = parentScope.bindings[name] = {
@@ -1146,12 +1133,9 @@ function crawlProgramScope(parsed, scriptParser) {
1146
1133
  };
1147
1134
  if (child.params) {
1148
1135
  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) {
1136
+ const parsedParams = ast.tagParams(child.params);
1137
+ if (parsedParams) {
1138
+ for (const param of parsedParams) {
1155
1139
  checkForMutations(bodyScope, param);
1156
1140
  for (const name of getIdentifiers(param)) {
1157
1141
  bodyScope.bindings[name] = {
@@ -1165,19 +1149,16 @@ function crawlProgramScope(parsed, scriptParser) {
1165
1149
  }
1166
1150
  }
1167
1151
  }
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
- );
1152
+ const scriptBody = ast.scriptBody(child);
1153
+ if (scriptBody) {
1154
+ const nodes = potentialMutations.get(parentScope);
1155
+ if (nodes) {
1156
+ nodes.push(...scriptBody);
1157
+ } else {
1158
+ potentialMutations.set(parentScope, [
1159
+ ...scriptBody
1160
+ ]);
1161
+ }
1181
1162
  } else {
1182
1163
  visit(child.body, bodyScope);
1183
1164
  }
@@ -1187,22 +1168,13 @@ ${read({
1187
1168
  for (const attr of child.attrs) {
1188
1169
  switch (attr.type) {
1189
1170
  case 15 /* AttrSpread */: {
1190
- checkForMutations(
1191
- parentScope,
1192
- scriptParser.expressionAt(
1193
- attr.value.start,
1194
- read(attr.value)
1195
- )
1196
- );
1171
+ checkForMutations(parentScope, ast.attrSpread(attr));
1197
1172
  break;
1198
1173
  }
1199
1174
  case 10 /* AttrNamed */: {
1200
1175
  switch ((_a2 = attr.value) == null ? void 0 : _a2.type) {
1201
1176
  case 13 /* AttrValue */: {
1202
- let parsedValue = scriptParser.expressionAt(
1203
- attr.value.value.start,
1204
- read(attr.value.value)
1205
- );
1177
+ let parsedValue = ast.attrValue(attr.value);
1206
1178
  if (parsedValue) {
1207
1179
  if (!attr.value.bound) {
1208
1180
  checkForMutations(parentScope, parsedValue);
@@ -1252,13 +1224,7 @@ ${read({
1252
1224
  case 14 /* AttrMethod */: {
1253
1225
  checkForMutations(
1254
1226
  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
- )
1227
+ ast.attrMethod(attr.value)
1262
1228
  );
1263
1229
  break;
1264
1230
  }
@@ -1275,12 +1241,24 @@ ${read({
1275
1241
  }
1276
1242
  function checkForMutations(scope, node) {
1277
1243
  if (node) {
1278
- const nodes = nodesToCheckForMutations.get(scope);
1279
- if (nodes) {
1280
- nodes.push(node);
1281
- } else {
1282
- nodesToCheckForMutations.set(scope, [node]);
1283
- }
1244
+ traverse(node, (child) => {
1245
+ switch (child.type) {
1246
+ case "FunctionDeclaration":
1247
+ case "FunctionExpression":
1248
+ case "ObjectMethod":
1249
+ case "ArrowFunctionExpression":
1250
+ case "ClassMethod":
1251
+ case "ClassPrivateMethod": {
1252
+ const nodes = potentialMutations.get(scope);
1253
+ if (nodes) {
1254
+ nodes.push(child);
1255
+ } else {
1256
+ potentialMutations.set(scope, [child]);
1257
+ }
1258
+ return true;
1259
+ }
1260
+ }
1261
+ });
1284
1262
  }
1285
1263
  }
1286
1264
  }
@@ -1459,32 +1437,13 @@ function* getVarIdentifiers(parsed, lVal, objectPath, sourceName) {
1459
1437
  break;
1460
1438
  }
1461
1439
  }
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) {
1440
+ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockMutations) {
1480
1441
  if (!node) return;
1481
- let block = parentBlock;
1482
1442
  let blockShadows = parentBlockShadows;
1483
1443
  let blockMutations = parentBlockMutations;
1484
1444
  switch (node.type) {
1485
1445
  case "BlockStatement":
1486
- if (block !== node) {
1487
- block = node;
1446
+ if (blockMutations === parentBlockMutations) {
1488
1447
  blockShadows = new Set(blockShadows);
1489
1448
  blockMutations = [];
1490
1449
  }
@@ -1492,12 +1451,10 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1492
1451
  case "ForStatement":
1493
1452
  case "ForInStatement":
1494
1453
  case "ForOfStatement":
1495
- block = node.body;
1496
1454
  blockShadows = new Set(blockShadows);
1497
1455
  blockMutations = [];
1498
1456
  break;
1499
1457
  case "ArrowFunctionExpression":
1500
- block = node.body;
1501
1458
  blockShadows = new Set(blockShadows);
1502
1459
  blockMutations = [];
1503
1460
  for (const param of node.params) {
@@ -1507,7 +1464,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1507
1464
  case "ObjectMethod":
1508
1465
  case "ClassMethod":
1509
1466
  case "ClassPrivateMethod":
1510
- block = node.body;
1511
1467
  blockShadows = new Set(blockShadows);
1512
1468
  blockMutations = [];
1513
1469
  for (const param of node.params) {
@@ -1515,7 +1471,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1515
1471
  }
1516
1472
  break;
1517
1473
  case "FunctionExpression":
1518
- block = node.body;
1519
1474
  blockShadows = new Set(blockShadows);
1520
1475
  blockMutations = [];
1521
1476
  if (node.id) {
@@ -1527,7 +1482,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1527
1482
  break;
1528
1483
  case "FunctionDeclaration":
1529
1484
  trackShadows(node.id, scope, parentBlockShadows);
1530
- block = node.body;
1531
1485
  blockShadows = new Set(blockShadows);
1532
1486
  blockMutations = [];
1533
1487
  for (const param of node.params) {
@@ -1535,7 +1489,6 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1535
1489
  }
1536
1490
  break;
1537
1491
  case "ClassExpression":
1538
- block = node.body;
1539
1492
  blockShadows = new Set(blockShadows);
1540
1493
  blockMutations = [];
1541
1494
  if (node.id) {
@@ -1546,12 +1499,10 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1546
1499
  if (node.id) {
1547
1500
  trackShadows(node.id, scope, parentBlockShadows);
1548
1501
  }
1549
- block = node.body;
1550
1502
  blockShadows = new Set(blockShadows);
1551
1503
  blockMutations = [];
1552
1504
  break;
1553
1505
  case "CatchClause":
1554
- block = node.body;
1555
1506
  blockShadows = new Set(blockShadows);
1556
1507
  blockMutations = [];
1557
1508
  if (node.param) {
@@ -1578,34 +1529,23 @@ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows,
1578
1529
  const child = node[key];
1579
1530
  if (Array.isArray(child)) {
1580
1531
  for (const item of child) {
1581
- trackMutations(
1582
- item,
1583
- scope,
1584
- mutations,
1585
- block,
1586
- blockShadows,
1587
- blockMutations
1588
- );
1532
+ trackMutations(item, scope, mutations, blockShadows, blockMutations);
1589
1533
  }
1590
1534
  } else {
1591
- trackMutations(
1592
- child,
1593
- scope,
1594
- mutations,
1595
- block,
1596
- blockShadows,
1597
- blockMutations
1598
- );
1535
+ trackMutations(child, scope, mutations, blockShadows, blockMutations);
1599
1536
  }
1600
1537
  }
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
- }
1538
+ if (blockMutations !== parentBlockMutations && blockMutations.length) {
1539
+ flushMutations(scope, mutations, blockShadows, blockMutations);
1540
+ }
1541
+ }
1542
+ function flushMutations(scope, mutations, blockShadows, blockMutations) {
1543
+ for (const { name, start } of blockMutations) {
1544
+ if (start == null || blockShadows.has(name)) continue;
1545
+ const binding = resolveWritableVar(scope, name);
1546
+ if (binding) {
1547
+ binding.mutated = true;
1548
+ mutations.push({ start, binding });
1609
1549
  }
1610
1550
  }
1611
1551
  }
@@ -1792,6 +1732,19 @@ function detectAPIFromTag(parsed, tag) {
1792
1732
  return detectAPIFromBody(parsed, tag.body);
1793
1733
  }
1794
1734
 
1735
+ // src/extractors/script/util/is-text-only-script.ts
1736
+ function isTextOnlyScript(tag) {
1737
+ if (tag.nameText !== "script" || tag.args || tag.attrs || !tag.body) {
1738
+ return false;
1739
+ }
1740
+ for (const child of tag.body) {
1741
+ if (child.type !== 17 /* Text */) {
1742
+ return false;
1743
+ }
1744
+ }
1745
+ return true;
1746
+ }
1747
+
1795
1748
  // src/extractors/script/util/jsdoc-input-type.ts
1796
1749
  var MaybeInputTypedefReg = /@typedef\b[\s\S]*\bInput\b/;
1797
1750
  function getJSDocInputType(comment, ts) {
@@ -1909,13 +1862,137 @@ import {
1909
1862
  var plugins = ["exportDefaultFrom", "importAssertions", "typescript"];
1910
1863
  var ScriptParser = class {
1911
1864
  #parsed;
1865
+ #cache = /* @__PURE__ */ new Map();
1912
1866
  constructor(parsed) {
1913
1867
  this.#parsed = parsed;
1914
1868
  }
1915
- statementAt(startIndex, src) {
1916
- const pos = this.#parsed.positionAt(startIndex);
1869
+ tagName(name) {
1870
+ return this.#templateExpressions(name);
1871
+ }
1872
+ tagShorthandId(shorthandId) {
1873
+ return this.#templateExpressions(shorthandId);
1874
+ }
1875
+ tagShorthandClassName(node) {
1876
+ return this.#templateExpressions(node);
1877
+ }
1878
+ tagVar(node) {
1879
+ const start = node.value.start - 1;
1880
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `(${this.#parsed.read(node.value)})=>0`);
1881
+ if (expr) {
1882
+ return expr.params[0];
1883
+ }
1884
+ }
1885
+ tagParams(node) {
1886
+ const start = node.start;
1887
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `(${this.#parsed.read(node.value)})=>0`);
1888
+ if (expr) {
1889
+ return expr.params;
1890
+ }
1891
+ }
1892
+ tagTypeParams(node) {
1893
+ const start = node.value.start - 1;
1894
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `<${this.#parsed.read(node.value)}>()=>0`);
1895
+ if (expr) {
1896
+ return expr.typeParameters;
1897
+ }
1898
+ }
1899
+ tagArgs(node) {
1900
+ const start = node.value.start - 2;
1901
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `_(${this.#parsed.read(node.value)})`);
1902
+ if (expr) {
1903
+ return expr.arguments;
1904
+ }
1905
+ }
1906
+ tagTypeArgs(node) {
1907
+ const start = node.value.start - 2;
1908
+ const expr = this.#cache.get(start) ?? this.#expressionAt(start, `_<${this.#parsed.read(node.value)}>()`);
1909
+ if (expr) {
1910
+ return expr.typeParameters;
1911
+ }
1912
+ }
1913
+ attrValue(node) {
1914
+ const start = node.value.start;
1915
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1916
+ }
1917
+ attrSpread(node) {
1918
+ const start = node.value.start;
1919
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1920
+ }
1921
+ attrMethod(node) {
1922
+ const start = node.params.start - 2;
1923
+ const expr = this.#cache.get(start) ?? this.#expressionAt(
1924
+ start,
1925
+ `{_${this.#parsed.read({ start: node.params.start, end: node.body.end })}}`
1926
+ );
1927
+ if (expr) {
1928
+ return expr.properties[0];
1929
+ }
1930
+ }
1931
+ attrArgs(node) {
1932
+ const start = node.value.start;
1933
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1934
+ }
1935
+ placeholder(node) {
1936
+ const start = node.value.start;
1937
+ return (this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(node.value))) || void 0;
1938
+ }
1939
+ scriptBody(node) {
1940
+ if (!isTextOnlyScript(node)) return;
1941
+ const start = node.body[0].start;
1942
+ const statements = this.#cache.get(start) ?? this.#statementsAt(
1943
+ start,
1944
+ this.#parsed.read({ start, end: node.body[node.body.length - 1].end })
1945
+ );
1946
+ if (statements) {
1947
+ return statements;
1948
+ }
1949
+ }
1950
+ scriptlet(node) {
1951
+ const start = node.value.start;
1952
+ const statements = this.#cache.get(start) ?? this.#statementsAt(start, this.#parsed.read(node.value));
1953
+ if (statements) {
1954
+ return statements;
1955
+ }
1956
+ }
1957
+ import(node) {
1958
+ const statements = this.#cache.get(node.start) ?? this.#statementsAt(node.start, this.#parsed.read(node));
1959
+ if (statements) {
1960
+ return statements[0];
1961
+ }
1962
+ }
1963
+ export(node) {
1964
+ const statements = this.#cache.get(node.start) ?? this.#statementsAt(node.start, this.#parsed.read(node));
1965
+ if (statements) {
1966
+ return statements[0];
1967
+ }
1968
+ }
1969
+ class(node) {
1970
+ const expr = this.#cache.get(node.start) ?? this.#expressionAt(node.start, this.#parsed.read(node));
1971
+ return expr || void 0;
1972
+ }
1973
+ static(node) {
1974
+ const start = node.start + "static ".length;
1975
+ const statements = this.#cache.get(start) ?? this.#statementsAt(start, this.#parsed.read({ start, end: node.end }));
1976
+ if (statements) {
1977
+ return statements;
1978
+ }
1979
+ }
1980
+ #templateExpressions(template) {
1981
+ const { expressions } = template;
1982
+ if (!expressions.length) return;
1983
+ const result = [];
1984
+ for (const expr of expressions) {
1985
+ const start = expr.value.start;
1986
+ const parsed = this.#cache.get(start) ?? this.#expressionAt(start, this.#parsed.read(expr.value));
1987
+ if (!parsed) return;
1988
+ result.push(parsed);
1989
+ }
1990
+ if (result.length) return result;
1991
+ }
1992
+ #statementsAt(startIndex, src) {
1917
1993
  try {
1918
- return parseStatement(src, {
1994
+ const pos = this.#parsed.positionAt(startIndex);
1995
+ const result = parseStatement(src, {
1919
1996
  plugins,
1920
1997
  startIndex,
1921
1998
  startLine: pos.line + 1,
@@ -1929,14 +2006,18 @@ var ScriptParser = class {
1929
2006
  allowReturnOutsideFunction: true,
1930
2007
  sourceFilename: this.#parsed.filename
1931
2008
  }).program.body;
2009
+ if (result.length) {
2010
+ this.#cache.set(startIndex, result);
2011
+ return result;
2012
+ }
1932
2013
  } catch {
1933
- return [];
1934
2014
  }
2015
+ this.#cache.set(startIndex, false);
1935
2016
  }
1936
- expressionAt(startIndex, src) {
1937
- const pos = this.#parsed.positionAt(startIndex);
2017
+ #expressionAt(startIndex, src) {
1938
2018
  try {
1939
- return parseExpression(src, {
2019
+ const pos = this.#parsed.positionAt(startIndex);
2020
+ const result = parseExpression(src, {
1940
2021
  plugins,
1941
2022
  startIndex,
1942
2023
  startLine: pos.line + 1,
@@ -1950,8 +2031,10 @@ var ScriptParser = class {
1950
2031
  allowReturnOutsideFunction: true,
1951
2032
  sourceFilename: this.#parsed.filename
1952
2033
  });
2034
+ this.#cache.set(startIndex, result);
2035
+ return result;
1953
2036
  } catch {
1954
- return;
2037
+ this.#cache.set(startIndex, false);
1955
2038
  }
1956
2039
  }
1957
2040
  };
@@ -1963,7 +2046,7 @@ var SEP_COMMA_SPACE = ", ";
1963
2046
  var SEP_COMMA_NEW_LINE = ",\n";
1964
2047
  var VAR_LOCAL_PREFIX = "__marko_internal_";
1965
2048
  var VAR_SHARED_PREFIX = `Marko._.`;
1966
- var ATTR_UNAMED2 = "value";
2049
+ var ATTR_UNNAMED2 = "value";
1967
2050
  var REG_EXT = /(?<=[/\\][^/\\]+)\.[^.]+$/;
1968
2051
  var REG_BLOCK = /\s*{/y;
1969
2052
  var REG_NEW_LINE = /^|(\r?\n)/g;
@@ -1994,7 +2077,7 @@ var ScriptExtractor = class {
1994
2077
  #interop;
1995
2078
  #parsed;
1996
2079
  #extractor;
1997
- #scriptParser;
2080
+ #ast;
1998
2081
  #read;
1999
2082
  #lookup;
2000
2083
  #scriptLang;
@@ -2020,9 +2103,9 @@ var ScriptExtractor = class {
2020
2103
  this.#ts = opts.ts;
2021
2104
  this.#runtimeTypes = opts.runtimeTypesCode;
2022
2105
  this.#extractor = new Extractor(parsed);
2023
- this.#scriptParser = new ScriptParser(parsed);
2106
+ this.#ast = new ScriptParser(parsed);
2024
2107
  this.#read = parsed.read.bind(parsed);
2025
- this.#mutations = crawlProgramScope(this.#parsed, this.#scriptParser);
2108
+ this.#mutations = crawlProgramScope(this.#parsed, this.#ast);
2026
2109
  this.#writeProgram(parsed.program);
2027
2110
  }
2028
2111
  end() {
@@ -2322,8 +2405,10 @@ function ${templateName}() {
2322
2405
  this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2323
2406
  `);
2324
2407
  if (scopeExpr) {
2325
- this.#extractor.write(`[${varShared("scope")}] = ${scopeExpr};
2326
- `);
2408
+ this.#extractor.write(
2409
+ `readonly [${varShared("scope")}] = ${scopeExpr};
2410
+ `
2411
+ );
2327
2412
  }
2328
2413
  this.#extractor.write(`declare return: Return;
2329
2414
  constructor(_?: Return) {}
@@ -2367,7 +2452,7 @@ constructor(_?: Return) {}
2367
2452
  }
2368
2453
  this.#writeComments(child);
2369
2454
  this.#extractor.write("if (").copy(
2370
- this.#getRangeWithoutTrailingComma((_a = child.args) == null ? void 0 : _a.value) || this.#getAttrValue(child, ATTR_UNAMED2) || "undefined"
2455
+ this.#getRangeWithoutTrailingComma((_a = child.args) == null ? void 0 : _a.value) || this.#getAttrValue(child, ATTR_UNNAMED2) || "undefined"
2371
2456
  ).write(") {\n");
2372
2457
  const ifBody = this.#processBody(child);
2373
2458
  if (ifBody == null ? void 0 : ifBody.content) {
@@ -2647,7 +2732,7 @@ scope: ${scopeExpr}
2647
2732
  const value = attr.value;
2648
2733
  const modifier = !value || value.type === 13 /* AttrValue */ ? this.#getNamedAttrModifier(attr) : void 0;
2649
2734
  const defaultMapPosition = isDefault ? attr.name : void 0;
2650
- let name = isDefault ? ATTR_UNAMED2 : attr.name;
2735
+ let name = isDefault ? ATTR_UNNAMED2 : attr.name;
2651
2736
  if (modifier) {
2652
2737
  name = { start: attr.name.start, end: modifier.start - 1 };
2653
2738
  }
@@ -2724,10 +2809,10 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2724
2809
  stringLiteralFirstArgMatch[2]
2725
2810
  );
2726
2811
  if (isValidProperty) {
2727
- const propertNameStart = stringLiteralStart + 1;
2812
+ const propertyNameStart = stringLiteralStart + 1;
2728
2813
  this.#extractor.write("component.").copy({
2729
- start: propertNameStart,
2730
- end: propertNameStart + stringLiteralValue.length
2814
+ start: propertyNameStart,
2815
+ end: propertyNameStart + stringLiteralValue.length
2731
2816
  });
2732
2817
  } else {
2733
2818
  this.#extractor.write(`component[`).copy({
@@ -2763,7 +2848,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2763
2848
  );
2764
2849
  return hasAttrs;
2765
2850
  }
2766
- #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }) {
2851
+ #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }, constraintExpr) {
2767
2852
  let wasMerge = false;
2768
2853
  if (dynamicAttrTagParents) {
2769
2854
  if (staticAttrTags) {
@@ -2784,7 +2869,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2784
2869
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2785
2870
  }
2786
2871
  if (dynamicAttrTagParents) {
2787
- this.#writeDynamicAttrTagParents(dynamicAttrTagParents);
2872
+ this.#writeDynamicAttrTagParents(dynamicAttrTagParents, constraintExpr);
2788
2873
  if (wasMerge) this.#extractor.write(`)${SEP_COMMA_NEW_LINE}`);
2789
2874
  }
2790
2875
  }
@@ -2800,18 +2885,8 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2800
2885
  if (isRepeated) {
2801
2886
  const templateVar = this.#getTemplateVar(firstAttrTag.owner);
2802
2887
  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
2888
  this.#extractor.write(
2814
- `${varShared("attrTagFor")}(${templateVar},${accessor})(`
2889
+ `${varShared("attrTagFor")}(${templateVar},${this.#getAttrTagPath(firstAttrTag)})(`
2815
2890
  );
2816
2891
  } else {
2817
2892
  this.#extractor.write(`${varShared("attrTag")}(`);
@@ -2833,7 +2908,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2833
2908
  }
2834
2909
  }
2835
2910
  }
2836
- #writeDynamicAttrTagParents(dynamicAttrTagParents) {
2911
+ #writeDynamicAttrTagParents(dynamicAttrTagParents, constraintExpr) {
2837
2912
  var _a, _b, _c;
2838
2913
  for (const tag of dynamicAttrTagParents) {
2839
2914
  switch (tag.nameText) {
@@ -2841,7 +2916,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2841
2916
  const alternates = IF_TAG_ALTERNATES.get(tag);
2842
2917
  this.#writeComments(tag);
2843
2918
  this.#extractor.write("((\n").copy(
2844
- this.#getRangeWithoutTrailingComma((_a = tag.args) == null ? void 0 : _a.value) || this.#getAttrValue(tag, ATTR_UNAMED2) || "undefined"
2919
+ this.#getRangeWithoutTrailingComma((_a = tag.args) == null ? void 0 : _a.value) || this.#getAttrValue(tag, ATTR_UNNAMED2) || "undefined"
2845
2920
  ).write("\n) ? ");
2846
2921
  this.#writeDynamicAttrTagBody(tag);
2847
2922
  let needsAlternate = true;
@@ -2875,8 +2950,12 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2875
2950
  this.#extractor.write("\n}, \n");
2876
2951
  this.#writeComments(tag);
2877
2952
  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("))");
2953
+ this.#writeDynamicAttrTagBody(tag, constraintExpr);
2954
+ this.#extractor.write(")");
2955
+ if (constraintExpr) {
2956
+ this.#extractor.write(`,${constraintExpr}`);
2957
+ }
2958
+ this.#extractor.write(")");
2880
2959
  break;
2881
2960
  }
2882
2961
  case "while": {
@@ -2934,7 +3013,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2934
3013
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2935
3014
  } else if (body) {
2936
3015
  hasInput = true;
2937
- this.#writeAttrTags(body);
3016
+ this.#writeAttrTags(body, this.#getTagInputType(tag));
2938
3017
  hasBodyContent = body.content !== void 0;
2939
3018
  } else if (tag.close) {
2940
3019
  hasBodyContent = true;
@@ -3097,7 +3176,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3097
3176
  const alternate = {
3098
3177
  condition: this.#getRangeWithoutTrailingComma(
3099
3178
  (_a = nextChild.args) == null ? void 0 : _a.value
3100
- ) || this.#getAttrValue(nextChild, ATTR_UNAMED2),
3179
+ ) || this.#getAttrValue(nextChild, ATTR_UNNAMED2),
3101
3180
  node: nextChild
3102
3181
  };
3103
3182
  hasDynamicAttrTags ||= nextChild.hasAttrTags;
@@ -3170,7 +3249,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3170
3249
  return { content, staticAttrTags, dynamicAttrTagParents };
3171
3250
  }
3172
3251
  }
3173
- #writeDynamicAttrTagBody(tag) {
3252
+ #writeDynamicAttrTagBody(tag, constraintExpr) {
3174
3253
  const body = this.#processBody(tag);
3175
3254
  if (body) {
3176
3255
  if (body.content) {
@@ -3179,7 +3258,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3179
3258
  this.#extractor.write("return ");
3180
3259
  }
3181
3260
  this.#extractor.write("{\n");
3182
- this.#writeAttrTags(body);
3261
+ this.#writeAttrTags(body, constraintExpr);
3183
3262
  this.#extractor.write("}");
3184
3263
  if (body.content) {
3185
3264
  this.#endChildren();
@@ -3192,7 +3271,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3192
3271
  #getAttrValue(tag, name) {
3193
3272
  if (tag.attrs) {
3194
3273
  for (const attr of tag.attrs) {
3195
- if (isValueAttribute(attr) && (this.#read(attr.name) || ATTR_UNAMED2) === name) {
3274
+ if (isValueAttribute(attr) && (this.#read(attr.name) || ATTR_UNNAMED2) === name) {
3196
3275
  return attr.value.value;
3197
3276
  }
3198
3277
  }
@@ -3230,9 +3309,9 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3230
3309
  var _a;
3231
3310
  for (const node of program.static) {
3232
3311
  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 }));
3312
+ if (this.#testAtIndex(REG_INPUT_TYPE, node.start + "export ".length)) {
3313
+ const exported = this.#ast.export(node);
3314
+ const inputType = exported == null ? void 0 : exported.declaration;
3236
3315
  return {
3237
3316
  typeParameters: (_a = inputType == null ? void 0 : inputType.typeParameters) == null ? void 0 : _a.params.map((param) => {
3238
3317
  return {
@@ -3339,6 +3418,30 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3339
3418
  const { nameText } = tag;
3340
3419
  return ((_a = this.#lookup.getTag(nameText)) == null ? void 0 : _a.targetProperty) || nameText.slice(nameText.lastIndexOf(":") + 1);
3341
3420
  }
3421
+ #getAttrTagPath(tag) {
3422
+ let path4 = `"${this.#getAttrTagName(tag)}"`;
3423
+ let curTag = tag.parent;
3424
+ while (curTag) {
3425
+ if (curTag.type === 16 /* AttrTag */) {
3426
+ path4 = `"${this.#getAttrTagName(curTag)}",${path4}`;
3427
+ } else if (!isControlFlowTag(curTag)) {
3428
+ break;
3429
+ }
3430
+ curTag = curTag.parent;
3431
+ }
3432
+ return path4;
3433
+ }
3434
+ #getTagInputType(tag) {
3435
+ if (tag.type === 16 /* AttrTag */) {
3436
+ if (!tag.owner) return;
3437
+ const templateVar2 = this.#getTemplateVar(tag.owner);
3438
+ if (!templateVar2) return;
3439
+ return `${varShared("inputForAttr")}(${templateVar2},${this.#getAttrTagPath(tag)})`;
3440
+ }
3441
+ const templateVar = this.#getTemplateVar(tag);
3442
+ if (!templateVar) return;
3443
+ return `${varShared("input")}(${templateVar})`;
3444
+ }
3342
3445
  #writeAttrTagTree(tree, valueExpression, nested) {
3343
3446
  this.#extractor.write(
3344
3447
  `${varShared(nested ? "nestedAttrTagNames" : "attrTagNames")}(${valueExpression},input=>{
@@ -3928,7 +4031,7 @@ var marko_default = {
3928
4031
  isExportComponentType(statement) || // skips the generated `export { type Component }`.
3929
4032
  isImportComponentType(statement) || // skips the generated `import type Component from "..."`.
3930
4033
  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.
4034
+ isExportInputTypeAsComponentInput(statement) || // skips outputting `export type Input = Component["input"]` since it's inferred.
3932
4035
  defaultExportId && // If the `export default` was an identifier, we also remove the variable that declared the identifier.
3933
4036
  isVariableStatementForName(statement, defaultExportId)) {
3934
4037
  continue;