@marko/language-tools 2.5.61 → 2.5.62

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
@@ -648,8 +648,14 @@ var emptyView = {
648
648
  offsetAt(_offset) {
649
649
  return;
650
650
  },
651
+ offsetsAt(_offset) {
652
+ return [];
653
+ },
651
654
  rangeAt(_start, _end) {
652
655
  return;
656
+ },
657
+ tokensIn(_start, _end) {
658
+ return [];
653
659
  }
654
660
  };
655
661
  var Extractor = class {
@@ -668,16 +674,46 @@ var Extractor = class {
668
674
  if (typeof range === "string") {
669
675
  this.#generated += range;
670
676
  } else {
677
+ let linkedSources;
678
+ let mapping = 0 /* full */;
679
+ if (Array.isArray(range)) {
680
+ if (!range.length) return this;
681
+ if (range.length > 1) linkedSources = range.slice(1);
682
+ mapping = 1 /* alias */;
683
+ range = range[0];
684
+ }
685
+ const { code } = this.#parsed;
686
+ const sourceStart = Math.min(range.start, code.length);
687
+ const length = Math.max(sourceStart, Math.min(code.length, range.end)) - sourceStart;
671
688
  this.#tokens.push({
672
689
  generatedStart: this.#generated.length,
673
- sourceStart: range.start,
674
- length: Math.min(this.#parsed.code.length, range.end) - range.start
690
+ sourceStart,
691
+ generatedLength: length,
692
+ sourceLength: length,
693
+ mapping,
694
+ linkedSources
675
695
  });
676
- this.#generated += this.#parsed.read(range);
696
+ this.#generated += code.slice(sourceStart, sourceStart + length);
677
697
  }
678
698
  }
679
699
  return this;
680
700
  }
701
+ anchor(range) {
702
+ if (range) {
703
+ const { code } = this.#parsed;
704
+ const sourceStart = Math.min(range.start, code.length);
705
+ const length = Math.max(sourceStart, Math.min(code.length, range.end)) - sourceStart;
706
+ this.#tokens.push({
707
+ generatedStart: this.#generated.length,
708
+ sourceStart,
709
+ generatedLength: 0,
710
+ sourceLength: length,
711
+ mapping: 2 /* anchor */,
712
+ linkedSources: void 0
713
+ });
714
+ }
715
+ return this;
716
+ }
681
717
  end() {
682
718
  return new Extracted(this.#parsed, this.#generated, this.#tokens);
683
719
  }
@@ -686,32 +722,78 @@ var Extracted = class {
686
722
  constructor(parsed, generated, tokens) {
687
723
  this.parsed = parsed;
688
724
  this.#generated = generated;
689
- if (tokens.length === 0) {
690
- this.#generatedToSource = this.#sourceToGenerated = emptyView;
691
- } else {
692
- this.#generatedToSource = new GeneratedToSourceView(tokens);
693
- this.#sourceToGenerated = new SourceToGeneratedView(
694
- [...tokens].sort(sortBySourceThenGenerated)
695
- );
696
- }
725
+ this.#tokens = tokens;
697
726
  }
698
727
  parsed;
699
728
  #generated;
729
+ #tokens;
700
730
  #sourceToGenerated;
731
+ #sourceToGeneratedAll;
701
732
  #generatedToSource;
702
733
  #cachedGeneratedLines;
703
734
  get #generatedLines() {
704
735
  return this.#cachedGeneratedLines || (this.#cachedGeneratedLines = getLines(this.#generated));
705
736
  }
737
+ get #generatedToSourceView() {
738
+ return this.#generatedToSource ??= this.#tokens.length ? new GeneratedToSourceView(this.#tokens) : emptyView;
739
+ }
740
+ get #sourceToGeneratedView() {
741
+ if (this.#sourceToGenerated) return this.#sourceToGenerated;
742
+ let tokens;
743
+ for (const token of this.#tokens) {
744
+ if (token.mapping === 0 /* full */) {
745
+ if (tokens) tokens.push(token);
746
+ else tokens = [token];
747
+ }
748
+ }
749
+ return this.#sourceToGenerated = tokens ? new SourceToGeneratedView(tokens.sort(sortBySourceThenGenerated)) : emptyView;
750
+ }
751
+ get #sourceToGeneratedAllView() {
752
+ if (this.#sourceToGeneratedAll) return this.#sourceToGeneratedAll;
753
+ let hasAliases = false;
754
+ for (const token of this.#tokens) {
755
+ if (token.mapping === 1 /* alias */) {
756
+ hasAliases = true;
757
+ break;
758
+ }
759
+ }
760
+ if (!hasAliases) {
761
+ return this.#sourceToGeneratedAll = this.#sourceToGeneratedView;
762
+ }
763
+ const tokens = [];
764
+ for (const token of this.#tokens) {
765
+ if (token.mapping === 2 /* anchor */) continue;
766
+ tokens.push(token);
767
+ if (token.linkedSources) {
768
+ for (const link of token.linkedSources) {
769
+ const length = Math.min(
770
+ token.generatedLength,
771
+ Math.max(0, link.end - link.start)
772
+ );
773
+ tokens.push({
774
+ generatedStart: token.generatedStart,
775
+ sourceStart: link.start,
776
+ generatedLength: length,
777
+ sourceLength: length,
778
+ mapping: 1 /* alias */,
779
+ linkedSources: void 0
780
+ });
781
+ }
782
+ }
783
+ }
784
+ return this.#sourceToGeneratedAll = new SourceToGeneratedView(
785
+ tokens.sort(sortBySourceThenGenerated)
786
+ );
787
+ }
706
788
  sourceOffsetAt(generatedOffset) {
707
- return this.#generatedToSource.offsetAt(generatedOffset);
789
+ return this.#generatedToSourceView.offsetAt(generatedOffset);
708
790
  }
709
791
  sourcePositionAt(generatedOffset) {
710
792
  const sourceOffset = this.sourceOffsetAt(generatedOffset);
711
793
  if (sourceOffset !== void 0) return this.parsed.positionAt(sourceOffset);
712
794
  }
713
795
  sourceRangeAt(generatedStart, generatedEnd) {
714
- return this.#generatedToSource.rangeAt(generatedStart, generatedEnd);
796
+ return this.#generatedToSourceView.rangeAt(generatedStart, generatedEnd);
715
797
  }
716
798
  sourceLocationAt(generatedStart, generatedEnd) {
717
799
  const sourceRange = this.sourceRangeAt(generatedStart, generatedEnd);
@@ -720,7 +802,48 @@ var Extracted = class {
720
802
  }
721
803
  }
722
804
  generatedOffsetAt(sourceOffset) {
723
- return this.#sourceToGenerated.offsetAt(sourceOffset);
805
+ return this.#sourceToGeneratedView.offsetAt(sourceOffset);
806
+ }
807
+ generatedOffsetsAt(sourceOffset) {
808
+ const offsets = this.#sourceToGeneratedAllView.offsetsAt(sourceOffset);
809
+ return offsets.length > 1 ? [...new Set(offsets)].sort(compareNumbers) : offsets;
810
+ }
811
+ sourceRangesAt(generatedStart, generatedEnd) {
812
+ const result = [];
813
+ for (const token of this.#generatedToSourceView.tokensIn(
814
+ generatedStart,
815
+ generatedEnd
816
+ )) {
817
+ if (token.mapping === 2 /* anchor */) {
818
+ pushUniqueRange(
819
+ result,
820
+ token.sourceStart,
821
+ token.sourceStart + token.sourceLength
822
+ );
823
+ continue;
824
+ }
825
+ const relStart = Math.max(0, generatedStart - token.generatedStart);
826
+ const relEnd = Math.min(
827
+ token.generatedLength,
828
+ generatedEnd - token.generatedStart
829
+ );
830
+ pushUniqueRange(
831
+ result,
832
+ token.sourceStart + relStart,
833
+ token.sourceStart + relEnd
834
+ );
835
+ if (token.linkedSources) {
836
+ for (const link of token.linkedSources) {
837
+ const linkLength = Math.max(0, link.end - link.start);
838
+ pushUniqueRange(
839
+ result,
840
+ link.start + Math.min(relStart, linkLength),
841
+ link.start + Math.min(relEnd, linkLength)
842
+ );
843
+ }
844
+ }
845
+ }
846
+ return result;
724
847
  }
725
848
  generatedPositionAt(sourceOffset) {
726
849
  const generatedOffset = this.generatedOffsetAt(sourceOffset);
@@ -729,7 +852,7 @@ var Extracted = class {
729
852
  }
730
853
  }
731
854
  generatedRangeAt(sourceStart, sourceEnd) {
732
- return this.#sourceToGenerated.rangeAt(sourceStart, sourceEnd);
855
+ return this.#sourceToGeneratedView.rangeAt(sourceStart, sourceEnd);
733
856
  }
734
857
  generatedLocationAt(sourceStart, sourceEnd) {
735
858
  const generatedRange = this.generatedRangeAt(sourceStart, sourceEnd);
@@ -748,69 +871,152 @@ var Extracted = class {
748
871
  var TokenView = class {
749
872
  #tokens;
750
873
  #last;
874
+ #maxEnds;
751
875
  constructor(tokens) {
752
876
  this.#tokens = tokens;
753
877
  this.#last = tokens.length - 1;
754
878
  }
879
+ get #inMaxEnds() {
880
+ if (this.#maxEnds) return this.#maxEnds;
881
+ const tokens = this.#tokens;
882
+ const maxEnds = new Array(tokens.length);
883
+ let max = -1;
884
+ for (let i = 0; i < tokens.length; i++) {
885
+ const token = tokens[i];
886
+ const end = this.inStart(token) + this.inLength(token);
887
+ if (end > max) max = end;
888
+ maxEnds[i] = max;
889
+ }
890
+ return this.#maxEnds = maxEnds;
891
+ }
755
892
  offsetAt(offset) {
893
+ const token = this.#tokenAt(offset);
894
+ if (token) {
895
+ return this.outStart(token) + (offset - this.inStart(token));
896
+ }
897
+ }
898
+ offsetsAt(offset) {
899
+ const result = [];
900
+ const tokens = this.#tokens;
756
901
  let min = 0;
757
902
  let max = this.#last;
758
903
  while (min < max) {
759
904
  const mid = 1 + min + max >>> 1;
760
- if (this.inStart(this.#tokens[mid]) <= offset) {
905
+ if (this.inStart(tokens[mid]) <= offset) {
761
906
  min = mid;
762
907
  } else {
763
908
  max = mid - 1;
764
909
  }
765
910
  }
766
- const token = this.#tokens[min];
767
- const index = offset - this.inStart(token);
768
- if (index >= 0 && index <= token.length) {
769
- return this.outStart(token) + index;
911
+ const maxEnds = this.#inMaxEnds;
912
+ for (let i = min; i >= 0 && maxEnds[i] >= offset; i--) {
913
+ const token = tokens[i];
914
+ const index = offset - this.inStart(token);
915
+ if (index >= 0 && index <= this.inLength(token)) {
916
+ result.push(this.outStart(token) + index);
917
+ }
918
+ }
919
+ return result;
920
+ }
921
+ tokensIn(inStart, inEnd) {
922
+ const result = [];
923
+ const tokens = this.#tokens;
924
+ if (!tokens.length) return result;
925
+ const maxEnds = this.#inMaxEnds;
926
+ let min = 0;
927
+ let max = this.#last;
928
+ if (maxEnds[max] <= inStart) return result;
929
+ while (min < max) {
930
+ const mid = min + max >> 1;
931
+ if (maxEnds[mid] > inStart) {
932
+ max = mid;
933
+ } else {
934
+ min = mid + 1;
935
+ }
936
+ }
937
+ for (let i = max; i < tokens.length; i++) {
938
+ const token = tokens[i];
939
+ const tokenInStart = this.inStart(token);
940
+ if (tokenInStart >= inEnd) break;
941
+ if (tokenInStart + this.inLength(token) > inStart) {
942
+ result.push(token);
943
+ }
770
944
  }
945
+ return result;
771
946
  }
772
947
  rangeAt(inStart, inEnd) {
948
+ if (inStart >= inEnd) {
949
+ return this.#pointAt(inStart);
950
+ }
951
+ const tokens = this.#tokens;
952
+ const maxEnds = this.#inMaxEnds;
773
953
  let min = 0;
774
954
  let max = this.#last;
955
+ if (maxEnds[max] <= inStart) return this.#pointAt(inStart);
775
956
  while (min < max) {
776
957
  const mid = min + max >> 1;
777
- const token = this.#tokens[mid];
778
- const tokenInEnd = this.inStart(token) + token.length;
779
- if (tokenInEnd > inStart) {
958
+ if (maxEnds[mid] > inStart) {
780
959
  max = mid;
781
960
  } else {
782
961
  min = mid + 1;
783
962
  }
784
963
  }
785
- const startToken = this.#tokens[max];
964
+ const startToken = tokens[max];
786
965
  const startTokenInStart = this.inStart(startToken);
787
- if (startTokenInStart >= inEnd) return;
966
+ if (startTokenInStart >= inEnd) return this.#pointAt(inStart);
788
967
  max = this.#last;
789
968
  while (min < max) {
790
969
  const mid = 1 + min + max >>> 1;
791
- const token = this.#tokens[mid];
792
- const tokenEnd = this.inStart(token) + token.length;
793
- if (tokenEnd <= inEnd) {
970
+ if (this.inStart(tokens[mid]) < inEnd) {
794
971
  min = mid;
795
972
  } else {
796
973
  max = mid - 1;
797
974
  }
798
975
  }
799
- const endToken = this.#tokens[min];
800
- const endTokenInStart = this.inStart(endToken);
801
- const endTokenInEnd = endTokenInStart + endToken.length;
802
- if (endTokenInEnd < inStart) return;
803
- const startIndex = inStart - startTokenInStart;
804
- const endIndex = inEnd - endTokenInStart;
805
- const start = this.outStart(startToken) + Math.max(0, startIndex);
806
- const end = this.outStart(endToken) + Math.min(endToken.length, endIndex);
976
+ const endToken = tokens[min];
977
+ const start = this.outStart(startToken) + Math.max(0, inStart - startTokenInStart);
978
+ const end = this.outStart(endToken) + (endToken.mapping === 2 /* anchor */ ? endToken.sourceLength : Math.min(this.inLength(endToken), inEnd - this.inStart(endToken)));
979
+ if (end < start) {
980
+ return {
981
+ start,
982
+ end: this.outStart(startToken) + (startToken.mapping === 2 /* anchor */ ? startToken.sourceLength : Math.min(this.inLength(startToken), inEnd - startTokenInStart))
983
+ };
984
+ }
807
985
  return { start, end };
808
986
  }
987
+ #pointAt(offset) {
988
+ const out = this.offsetAt(offset);
989
+ if (out !== void 0) return { start: out, end: out };
990
+ }
991
+ #tokenAt(offset) {
992
+ const tokens = this.#tokens;
993
+ let min = 0;
994
+ let max = this.#last;
995
+ while (min < max) {
996
+ const mid = 1 + min + max >>> 1;
997
+ if (this.inStart(tokens[mid]) <= offset) {
998
+ min = mid;
999
+ } else {
1000
+ max = mid - 1;
1001
+ }
1002
+ }
1003
+ const maxEnds = this.#inMaxEnds;
1004
+ for (let i = min; i >= 0 && maxEnds[i] >= offset; i--) {
1005
+ const token = tokens[i];
1006
+ const index = offset - this.inStart(token);
1007
+ if (index >= 0 && index <= this.inLength(token)) {
1008
+ return token;
1009
+ }
1010
+ }
1011
+ }
809
1012
  };
810
1013
  var GeneratedToSourceView = class extends TokenView {
811
1014
  inStart(token) {
812
1015
  return token.generatedStart;
813
1016
  }
1017
+ inLength(token) {
1018
+ return token.generatedLength;
1019
+ }
814
1020
  outStart(token) {
815
1021
  return token.sourceStart;
816
1022
  }
@@ -819,6 +1025,9 @@ var SourceToGeneratedView = class extends TokenView {
819
1025
  inStart(token) {
820
1026
  return token.sourceStart;
821
1027
  }
1028
+ inLength(token) {
1029
+ return token.sourceLength;
1030
+ }
822
1031
  outStart(token) {
823
1032
  return token.generatedStart;
824
1033
  }
@@ -827,6 +1036,15 @@ function sortBySourceThenGenerated(a, b) {
827
1036
  const delta = a.sourceStart - b.sourceStart;
828
1037
  return delta === 0 ? b.generatedStart - a.generatedStart : delta;
829
1038
  }
1039
+ function compareNumbers(a, b) {
1040
+ return a - b;
1041
+ }
1042
+ function pushUniqueRange(ranges, start, end) {
1043
+ for (const range of ranges) {
1044
+ if (range.start === start && range.end === end) return;
1045
+ }
1046
+ ranges.push({ start, end });
1047
+ }
830
1048
 
831
1049
  // src/extractors/html/keywords.ts
832
1050
  var builtinTagsRegex = (
@@ -1243,6 +1461,7 @@ function crawlProgramScope(parsed, ast) {
1243
1461
  const mutations = [];
1244
1462
  const potentialHoists = [];
1245
1463
  const potentialMutations = /* @__PURE__ */ new Map();
1464
+ const analyzeMutations = hasTagVars(program.body);
1246
1465
  const programScope = {
1247
1466
  parent: void 0,
1248
1467
  hoists: false,
@@ -1318,7 +1537,7 @@ function crawlProgramScope(parsed, ast) {
1318
1537
  "",
1319
1538
  ATTR_UNNAMED
1320
1539
  )) {
1321
- const { name, objectPath, sourceName } = id;
1540
+ const { name, range, objectPath, sourceName } = id;
1322
1541
  const binding = parentScope.bindings[name] = {
1323
1542
  type: 0 /* var */,
1324
1543
  name,
@@ -1326,6 +1545,7 @@ function crawlProgramScope(parsed, ast) {
1326
1545
  scope: parentScope,
1327
1546
  hoisted: false,
1328
1547
  mutated: false,
1548
+ range,
1329
1549
  objectPath,
1330
1550
  sourceName
1331
1551
  };
@@ -1339,7 +1559,7 @@ function crawlProgramScope(parsed, ast) {
1339
1559
  hoists: false,
1340
1560
  bindings: {}
1341
1561
  };
1342
- if (child.params) {
1562
+ if (analyzeMutations && child.params) {
1343
1563
  bodyScope.bindings ??= {};
1344
1564
  const parsedParams = ast.tagParams(child.params);
1345
1565
  if (parsedParams) {
@@ -1357,7 +1577,7 @@ function crawlProgramScope(parsed, ast) {
1357
1577
  }
1358
1578
  }
1359
1579
  }
1360
- const scriptBody = ast.scriptBody(child);
1580
+ const scriptBody = analyzeMutations && ast.scriptBody(child);
1361
1581
  if (scriptBody) {
1362
1582
  const nodes = potentialMutations.get(parentScope);
1363
1583
  if (nodes) {
@@ -1376,12 +1596,15 @@ function crawlProgramScope(parsed, ast) {
1376
1596
  for (const attr of child.attrs) {
1377
1597
  switch (attr.type) {
1378
1598
  case 15 /* AttrSpread */: {
1379
- checkForMutations(parentScope, ast.attrSpread(attr));
1599
+ if (analyzeMutations) {
1600
+ checkForMutations(parentScope, ast.attrSpread(attr));
1601
+ }
1380
1602
  break;
1381
1603
  }
1382
1604
  case 10 /* AttrNamed */: {
1383
1605
  switch ((_a2 = attr.value) == null ? void 0 : _a2.type) {
1384
1606
  case 13 /* AttrValue */: {
1607
+ if (!analyzeMutations && !attr.value.bound) break;
1385
1608
  let parsedValue = ast.attrValue(attr.value);
1386
1609
  if (parsedValue) {
1387
1610
  if (!attr.value.bound) {
@@ -1430,10 +1653,12 @@ function crawlProgramScope(parsed, ast) {
1430
1653
  break;
1431
1654
  }
1432
1655
  case 14 /* AttrMethod */: {
1433
- checkForMutations(
1434
- parentScope,
1435
- ast.attrMethod(attr.value)
1436
- );
1656
+ if (analyzeMutations) {
1657
+ checkForMutations(
1658
+ parentScope,
1659
+ ast.attrMethod(attr.value)
1660
+ );
1661
+ }
1437
1662
  break;
1438
1663
  }
1439
1664
  }
@@ -1475,21 +1700,32 @@ function getProgramBindings(node) {
1475
1700
  let hoists;
1476
1701
  let vars;
1477
1702
  for (const key in bindings) {
1478
- switch (bindings[key].type) {
1479
- case 2 /* hoisted */:
1703
+ const binding = bindings[key];
1704
+ switch (binding.type) {
1705
+ case 2 /* hoisted */: {
1706
+ const hoist = {
1707
+ name: key,
1708
+ sources: binding.bindings.map((it) => it.range)
1709
+ };
1480
1710
  if (hoists) {
1481
- hoists.push(key);
1711
+ hoists.push(hoist);
1482
1712
  } else {
1483
- hoists = [key];
1713
+ hoists = [hoist];
1484
1714
  }
1485
1715
  break;
1486
- case 0 /* var */:
1716
+ }
1717
+ case 0 /* var */: {
1718
+ const tagVar = {
1719
+ name: key,
1720
+ sources: [binding.range]
1721
+ };
1487
1722
  if (vars) {
1488
- vars.push(key);
1723
+ vars.push(tagVar);
1489
1724
  } else {
1490
- vars = [key];
1725
+ vars = [tagVar];
1491
1726
  }
1492
1727
  break;
1728
+ }
1493
1729
  }
1494
1730
  }
1495
1731
  if (hoists || vars) {
@@ -1520,11 +1756,12 @@ function getHoistSources(body) {
1520
1756
  if (body) {
1521
1757
  const { bindings } = Scopes.get(body);
1522
1758
  for (const key in bindings) {
1523
- if (bindings[key].hoisted) {
1759
+ const binding = bindings[key];
1760
+ if (binding.hoisted) {
1524
1761
  if (result) {
1525
- result.push(key);
1762
+ result.push(binding);
1526
1763
  } else {
1527
- result = [key];
1764
+ result = [binding];
1528
1765
  }
1529
1766
  }
1530
1767
  }
@@ -1532,16 +1769,9 @@ function getHoistSources(body) {
1532
1769
  return result;
1533
1770
  }
1534
1771
  function isMutatedVar(node, name) {
1535
- var _a;
1536
- let scope = Scopes.get(node.body);
1537
- while (scope) {
1538
- const binding = (_a = scope.bindings) == null ? void 0 : _a[name];
1539
- if ((binding == null ? void 0 : binding.type) === 0 /* var */ && binding.mutated) {
1540
- return true;
1541
- }
1542
- scope = scope.parent;
1543
- }
1544
- return false;
1772
+ const scope = Scopes.get(node.body);
1773
+ const binding = scope && resolveWritableVar(scope, name);
1774
+ return binding ? binding.mutated : false;
1545
1775
  }
1546
1776
  function hasHoists(node) {
1547
1777
  return node.body ? Scopes.get(node.body).hoists : false;
@@ -1549,27 +1779,47 @@ function hasHoists(node) {
1549
1779
  function getBoundAttrRange(value) {
1550
1780
  return BoundAttrValueRange.get(value);
1551
1781
  }
1782
+ function hasTagVars(body) {
1783
+ if (body) {
1784
+ for (const child of body) {
1785
+ switch (child.type) {
1786
+ case 1 /* Tag */:
1787
+ case 16 /* AttrTag */:
1788
+ if (child.var || hasTagVars(child.body)) {
1789
+ return true;
1790
+ }
1791
+ break;
1792
+ }
1793
+ }
1794
+ }
1795
+ return false;
1796
+ }
1552
1797
  function resolveWritableVar(scope, name) {
1553
1798
  var _a;
1554
1799
  let curScope = scope;
1555
1800
  do {
1556
1801
  const binding = (_a = curScope.bindings) == null ? void 0 : _a[name];
1557
- if ((binding == null ? void 0 : binding.type) === 0 /* var */ && binding.sourceName !== void 0) {
1558
- return binding;
1802
+ if (binding) {
1803
+ return binding.type === 0 /* var */ && binding.sourceName !== void 0 ? binding : void 0;
1559
1804
  }
1560
1805
  } while (curScope = curScope.parent);
1561
1806
  }
1562
1807
  function* getIdentifiers(lVal) {
1808
+ for (const id of getIdentifierNodes(lVal)) {
1809
+ yield id.name;
1810
+ }
1811
+ }
1812
+ function* getIdentifierNodes(lVal) {
1563
1813
  switch (lVal.type) {
1564
1814
  case "Identifier":
1565
- yield lVal.name;
1815
+ yield lVal;
1566
1816
  break;
1567
1817
  case "ObjectPattern":
1568
1818
  for (const prop of lVal.properties) {
1569
1819
  if (prop.type === "RestElement") {
1570
- yield* getIdentifiers(prop.argument);
1820
+ yield* getIdentifierNodes(prop.argument);
1571
1821
  } else {
1572
- yield* getIdentifiers(prop.value);
1822
+ yield* getIdentifierNodes(prop.value);
1573
1823
  }
1574
1824
  }
1575
1825
  break;
@@ -1577,15 +1827,15 @@ function* getIdentifiers(lVal) {
1577
1827
  for (const element of lVal.elements) {
1578
1828
  if (element) {
1579
1829
  if (element.type === "RestElement") {
1580
- yield* getIdentifiers(element.argument);
1830
+ yield* getIdentifierNodes(element.argument);
1581
1831
  } else {
1582
- yield* getIdentifiers(element);
1832
+ yield* getIdentifierNodes(element);
1583
1833
  }
1584
1834
  }
1585
1835
  }
1586
1836
  break;
1587
1837
  case "AssignmentPattern":
1588
- yield* getIdentifiers(lVal.left);
1838
+ yield* getIdentifierNodes(lVal.left);
1589
1839
  break;
1590
1840
  }
1591
1841
  }
@@ -1594,6 +1844,7 @@ function* getVarIdentifiers(parsed, lVal, objectPath, sourceName) {
1594
1844
  case "Identifier":
1595
1845
  yield {
1596
1846
  name: lVal.name,
1847
+ range: { start: lVal.start, end: lVal.start + lVal.name.length },
1597
1848
  objectPath,
1598
1849
  sourceName
1599
1850
  };
@@ -1656,9 +1907,17 @@ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockM
1656
1907
  blockMutations = [];
1657
1908
  }
1658
1909
  break;
1659
- case "ForStatement":
1660
1910
  case "ForInStatement":
1661
1911
  case "ForOfStatement":
1912
+ if (node.left.type !== "VariableDeclaration") {
1913
+ for (const id of getIdentifierNodes(node.left)) {
1914
+ parentBlockMutations.push(id);
1915
+ }
1916
+ }
1917
+ blockShadows = new Set(blockShadows);
1918
+ blockMutations = [];
1919
+ break;
1920
+ case "ForStatement":
1662
1921
  blockShadows = new Set(blockShadows);
1663
1922
  blockMutations = [];
1664
1923
  break;
@@ -1689,7 +1948,9 @@ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockM
1689
1948
  }
1690
1949
  break;
1691
1950
  case "FunctionDeclaration":
1692
- trackShadows(node.id, scope, parentBlockShadows);
1951
+ if (node.id) {
1952
+ trackShadows(node.id, scope, parentBlockShadows);
1953
+ }
1693
1954
  blockShadows = new Set(blockShadows);
1694
1955
  blockMutations = [];
1695
1956
  for (const param of node.params) {
@@ -1730,6 +1991,10 @@ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockM
1730
1991
  case "AssignmentExpression":
1731
1992
  if (node.left.type === "Identifier") {
1732
1993
  parentBlockMutations.push(node.left);
1994
+ } else {
1995
+ for (const id of getIdentifierNodes(node.left)) {
1996
+ parentBlockMutations.push(id);
1997
+ }
1733
1998
  }
1734
1999
  break;
1735
2000
  }
@@ -2060,7 +2325,7 @@ var ATTR_UNNAMED2 = "value";
2060
2325
  var REG_EXT = /(?<=[/\\][^/\\]+)\.[^.]+$/;
2061
2326
  var REG_BLOCK = /\s*{/y;
2062
2327
  var REG_NEW_LINE = /^|(\r?\n)/g;
2063
- var REG_ATTR_ARG_LITERAL = /(?<=\s*)(["'])((?:[^"'\\]|\\.|(?!\1))*)\1\s*([,)])/my;
2328
+ var REG_ATTR_ARG_LITERAL = /(["'])((?:\\.|(?!\1)[^\\])*)\1\s*([,)])/y;
2064
2329
  var REG_TAG_IMPORT = /(?<=(['"]))<([^'">]+)>(?=\1)/;
2065
2330
  var REG_INPUT_TYPE = /\s*(interface|type)\s+Input\b/y;
2066
2331
  var REG_OBJECT_PROPERTY = /^[_$a-z][_$a-z0-9]*$/i;
@@ -2152,11 +2417,12 @@ var ScriptExtractor = class {
2152
2417
  if (templatePath) {
2153
2418
  const [{ length }] = tagImportMatch;
2154
2419
  const fromStart = node.start + tagImportMatch.index;
2420
+ const fromEnd = fromStart + length;
2155
2421
  this.#extractor.copy({
2156
2422
  start: node.start,
2157
2423
  end: fromStart
2158
2424
  }).write(templatePath).copy({
2159
- start: fromStart + length,
2425
+ start: fromEnd,
2160
2426
  end: node.end
2161
2427
  }).write("\n");
2162
2428
  break;
@@ -2288,9 +2554,9 @@ function ${templateName}() {
2288
2554
  const body = this.#processBody(program);
2289
2555
  const bindings = getProgramBindings(program);
2290
2556
  if (bindings) {
2291
- for (const name of bindings.all) {
2292
- this.#extractor.write(
2293
- `const ${name} = ${varShared("hoist")}(() => ${varLocal(`hoist__${name}`)});
2557
+ for (const binding of bindings.all) {
2558
+ this.#extractor.write("const ").copy(binding.sources).write(
2559
+ ` = ${varShared("hoist")}(() => ${varLocal(`hoist__${binding.name}`)});
2294
2560
  `
2295
2561
  );
2296
2562
  }
@@ -2299,16 +2565,17 @@ function ${templateName}() {
2299
2565
  this.#writeChildren(body.content);
2300
2566
  if (bindings) {
2301
2567
  if (bindings.vars) {
2302
- for (const name of bindings.vars) {
2303
- this.#extractor.write(
2304
- `var ${varLocal(`hoist__${name}`)} = ${name};
2305
- `
2306
- );
2568
+ for (const binding of bindings.vars) {
2569
+ this.#extractor.write(`var ${varLocal(`hoist__${binding.name}`)} = `).copy(binding.sources[0]).write(";\n");
2307
2570
  }
2308
2571
  }
2309
2572
  if (bindings.hoists) {
2310
2573
  this.#extractor.write(
2311
- `var {${bindings.hoists.map((name) => `${name}: ${varLocal(`hoist__${name}`)}`).join(SEP_COMMA_SPACE)}} = ${this.#getBodyHoistScopeExpression(program.body)};
2574
+ `var {${bindings.hoists.map(
2575
+ (binding) => `${binding.name}: ${varLocal(`hoist__${binding.name}`)}`
2576
+ ).join(
2577
+ SEP_COMMA_SPACE
2578
+ )}} = ${this.#getBodyHoistScopeExpression(program.body)};
2312
2579
  `
2313
2580
  );
2314
2581
  }
@@ -2316,7 +2583,7 @@ function ${templateName}() {
2316
2583
  this.#endChildren();
2317
2584
  }
2318
2585
  this.#extractor.write(
2319
- `${varShared("noop")}({ ${bindings ? bindings.all.join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api === RuntimeAPI.class ? "component, state, out, " : ""}input, $global, $signal });
2586
+ `${varShared("noop")}({ ${bindings ? bindings.all.map((binding) => binding.name).join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api === RuntimeAPI.class ? "component, state, out, " : ""}input, $global, $signal });
2320
2587
  `
2321
2588
  );
2322
2589
  if (didReturn) {
@@ -2351,14 +2618,14 @@ function ${templateName}() {
2351
2618
  -1
2352
2619
  )}>${renderAndReturn};` : `(): () => <${internalInputWithExtends}>${renderAndReturn};`}
2353
2620
  }>`;
2354
- this.#extractor.copy(START_OF_FILE);
2621
+ this.#extractor.write(`export default new `).anchor(START_OF_FILE);
2355
2622
  if (this.#scriptLang === "ts" /* ts */) {
2356
- this.#extractor.write(`export default new (
2623
+ this.#extractor.write(`(
2357
2624
  class Template extends ${templateOverrideClass} {}
2358
2625
  );
2359
2626
  `);
2360
2627
  } else {
2361
- this.#extractor.write(`export default new (
2628
+ this.#extractor.write(`(
2362
2629
  /**
2363
2630
  * @extends {${removeNewLines(templateOverrideClass)}}
2364
2631
  */
@@ -2406,24 +2673,42 @@ function ${templateName}() {
2406
2673
  }
2407
2674
  }
2408
2675
  #writeReturn(returned, body) {
2409
- const scopeExpr = this.#getScopeExpression(body);
2410
- if (!returned && !scopeExpr) {
2676
+ const hasScope = this.#hasScopeExpression(body);
2677
+ if (!returned && !hasScope) {
2411
2678
  this.#extractor.write(`return ${varShared("voidReturn")};
2412
2679
  `);
2413
2680
  return;
2414
2681
  }
2415
- this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2682
+ if (this.#scriptLang === "ts" /* ts */) {
2683
+ this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2416
2684
  `);
2417
- if (scopeExpr) {
2418
- this.#extractor.write(
2419
- `readonly [${varShared("scope")}] = ${scopeExpr};
2420
- `
2421
- );
2422
- }
2423
- this.#extractor.write(`declare return: Return;
2685
+ if (hasScope) {
2686
+ this.#extractor.write(`readonly [${varShared("scope")}] = `);
2687
+ this.#writeScopeExpression(body);
2688
+ this.#extractor.write(";\n");
2689
+ }
2690
+ this.#extractor.write(`declare return: Return;
2424
2691
  constructor(_?: Return) {}
2425
2692
  })(
2426
2693
  `);
2694
+ } else {
2695
+ this.#extractor.write(`return new (/**
2696
+ * @template [Return=void]
2697
+ */
2698
+ class MarkoReturn {
2699
+ `);
2700
+ if (hasScope) {
2701
+ this.#extractor.write(`[${varShared("scope")}] = `);
2702
+ this.#writeScopeExpression(body);
2703
+ this.#extractor.write(";\n");
2704
+ }
2705
+ this.#extractor.write(`/** @type {Return} */
2706
+ return;
2707
+ /** @param {Return} [_] */
2708
+ constructor(_) {}
2709
+ })(
2710
+ `);
2711
+ }
2427
2712
  this.#extractor.copy(returned);
2428
2713
  this.#extractor.write(");\n");
2429
2714
  }
@@ -2467,12 +2752,10 @@ constructor(_?: Return) {}
2467
2752
  const ifBody = this.#processBody(child);
2468
2753
  if (ifBody == null ? void 0 : ifBody.content) {
2469
2754
  this.#writeChildren(ifBody.content, true);
2470
- const scopeExpr = this.#getScopeExpression(child.body);
2471
- if (scopeExpr) {
2472
- this.#extractor.write(`return {
2473
- scope: ${scopeExpr}
2474
- };
2475
- `);
2755
+ if (this.#hasScopeExpression(child.body)) {
2756
+ this.#extractor.write("return {\nscope: ");
2757
+ this.#writeScopeExpression(child.body);
2758
+ this.#extractor.write("\n};\n");
2476
2759
  }
2477
2760
  this.#endChildren();
2478
2761
  }
@@ -2491,14 +2774,10 @@ scope: ${scopeExpr}
2491
2774
  const alternateBody = this.#processBody(node);
2492
2775
  if (alternateBody == null ? void 0 : alternateBody.content) {
2493
2776
  this.#writeChildren(alternateBody.content, true);
2494
- const scopeExpr = this.#getScopeExpression(node.body);
2495
- if (scopeExpr) {
2496
- this.#extractor.write(
2497
- `return {
2498
- scope: ${scopeExpr}
2499
- };
2500
- `
2501
- );
2777
+ if (this.#hasScopeExpression(node.body)) {
2778
+ this.#extractor.write("return {\nscope: ");
2779
+ this.#writeScopeExpression(node.body);
2780
+ this.#extractor.write("\n};\n");
2502
2781
  }
2503
2782
  this.#endChildren();
2504
2783
  }
@@ -2523,8 +2802,7 @@ scope: ${scopeExpr}
2523
2802
  this.#extractor.write(
2524
2803
  `${varShared(getForTagRuntime(this.#parsed, child))}({
2525
2804
  `
2526
- );
2527
- this.#writeTagNameComment(child);
2805
+ ).anchor(child.name);
2528
2806
  this.#writeAttrs(child);
2529
2807
  this.#extractor.write("\n}" + SEP_COMMA_NEW_LINE).copy(child.typeParams).write("(\n");
2530
2808
  this.#writeComments(child);
@@ -2646,9 +2924,7 @@ scope: ${scopeExpr}
2646
2924
  } else if (templateVar) {
2647
2925
  this.#extractor.write(
2648
2926
  `${varShared(isTemplate ? "renderTemplate" : "renderDynamicTag")}(${templateVar}`
2649
- );
2650
- this.#writeTagNameComment(tag);
2651
- this.#extractor.write(")");
2927
+ ).anchor(tag.name).write(")");
2652
2928
  } else {
2653
2929
  this.#extractor.write(varShared("missingTag"));
2654
2930
  }
@@ -2682,9 +2958,6 @@ scope: ${scopeExpr}
2682
2958
  this.#extractor.write(`${varShared("interpolated")}\``).copy(tag.name).write("`");
2683
2959
  }
2684
2960
  }
2685
- #writeTagNameComment(tag) {
2686
- this.#extractor.write("/*").copy(this.#getDynamicTagExpression(tag) || tag.name).write("*/");
2687
- }
2688
2961
  #writePlaceholder(placeholder) {
2689
2962
  this.#writeComments(placeholder);
2690
2963
  this.#extractor.write("(").copy(placeholder.value).write(");\n");
@@ -2694,7 +2967,6 @@ scope: ${scopeExpr}
2694
2967
  this.#extractor.copy(scriptlet.value).write(";\n");
2695
2968
  }
2696
2969
  #writeAttrs(tag) {
2697
- var _a, _b, _c, _d, _e, _f;
2698
2970
  let hasAttrs = false;
2699
2971
  if (tag.shorthandId) {
2700
2972
  hasAttrs = true;
@@ -2716,19 +2988,9 @@ scope: ${scopeExpr}
2716
2988
  }
2717
2989
  this.#extractor.write("`" + SEP_COMMA_NEW_LINE);
2718
2990
  }
2719
- let attrWhitespaceStart = Math.max(
2720
- tag.name.end,
2721
- ((_a = tag.shorthandId) == null ? void 0 : _a.end) ?? -1,
2722
- ((_c = (_b = tag.shorthandClassNames) == null ? void 0 : _b[tag.shorthandClassNames.length - 1]) == null ? void 0 : _c.end) ?? -1,
2723
- ((_d = tag.var) == null ? void 0 : _d.end) ?? -1,
2724
- ((_e = tag.args) == null ? void 0 : _e.end) ?? -1,
2725
- ((_f = tag.params) == null ? void 0 : _f.end) ?? -1
2726
- );
2727
2991
  if (tag.attrs) {
2728
2992
  hasAttrs = true;
2729
2993
  for (const attr of tag.attrs) {
2730
- this.#copyWhitespaceWithin(attrWhitespaceStart, attr.start);
2731
- attrWhitespaceStart = attr.end;
2732
2994
  switch (attr.type) {
2733
2995
  case 15 /* AttrSpread */:
2734
2996
  this.#extractor.write(`...(
@@ -2749,18 +3011,18 @@ scope: ${scopeExpr}
2749
3011
  if (value) {
2750
3012
  switch (value.type) {
2751
3013
  case 14 /* AttrMethod */:
2752
- this.#extractor.write('"').copy(defaultMapPosition).copy(name).write('"').copy(value.typeParams);
3014
+ this.#extractor.write('"').anchor(defaultMapPosition).copy(name).write('"').copy(value.typeParams);
2753
3015
  this.#copyWithMutationsReplaced(value.params);
2754
3016
  this.#copyWithMutationsReplaced(value.body);
2755
3017
  break;
2756
3018
  case 13 /* AttrValue */: {
2757
3019
  const boundRange = value.bound && getBoundAttrRange(value);
2758
- this.#extractor.write('"').copy(defaultMapPosition).copy(name).write('": (\n');
3020
+ this.#extractor.write('"').anchor(defaultMapPosition).copy(name).write('": (\n');
2759
3021
  if (boundRange) {
2760
3022
  if (!boundRange.member) {
2761
3023
  const valueLiteral = this.#read(boundRange.value);
2762
3024
  this.#extractor.copy(boundRange.value).write(" ").copy(boundRange.types).write(`
2763
- )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write(
3025
+ )${SEP_COMMA_NEW_LINE}"`).anchor(defaultMapPosition).copy(name).write(
2764
3026
  `Change"(
2765
3027
  // @ts-ignore
2766
3028
  _${valueLiteral}
@@ -2776,7 +3038,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2776
3038
  start: boundRange.member.end,
2777
3039
  end: boundRange.member.end + 1
2778
3040
  }).copy(boundRange.types).write(`
2779
- )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write('Change": (\n');
3041
+ )${SEP_COMMA_NEW_LINE}"`).anchor(defaultMapPosition).copy(name).write('Change": (\n');
2780
3042
  if (modifier) {
2781
3043
  this.#extractor.copy(boundRange.value).write("[`${\n").copy(boundRange.member).write("\n}Change`] && ((\n// @ts-ignore\n_\n)=>{\n").copy(boundRange.value).write("[`${\n").copy(boundRange.member).write("\n}Change`](").copy(modifier).write("(_));\n})");
2782
3044
  } else {
@@ -2789,7 +3051,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2789
3051
  end: boundRange.member.end
2790
3052
  };
2791
3053
  this.#extractor.copy(memberRange).copy(boundRange.types).write(`
2792
- )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write('Change": (\n');
3054
+ )${SEP_COMMA_NEW_LINE}"`).anchor(defaultMapPosition).copy(name).write('Change": (\n');
2793
3055
  if (modifier) {
2794
3056
  this.#extractor.copy(memberRange).write("Change && ((\n// @ts-ignore\n_\n)=>{\n").copy(memberRange).write("Change(").copy(modifier).write("(_));\n})");
2795
3057
  } else {
@@ -2844,7 +3106,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2844
3106
  this.#extractor.copy(attr.args);
2845
3107
  }
2846
3108
  } else {
2847
- this.#extractor.write('"').copy(defaultMapPosition).copy(name).write(`": ${modifier ? '""' : "true"}`);
3109
+ this.#extractor.write('"').anchor(defaultMapPosition).copy(name).write(`": ${modifier ? '""' : "true"}`);
2848
3110
  }
2849
3111
  break;
2850
3112
  }
@@ -2852,10 +3114,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2852
3114
  this.#extractor.write(SEP_COMMA_NEW_LINE);
2853
3115
  }
2854
3116
  }
2855
- this.#copyWhitespaceWithin(
2856
- attrWhitespaceStart,
2857
- tag.open.end - (tag.concise ? this.#code[tag.open.end] === ";" ? 1 : 0 : tag.selfClosed ? 2 : 1)
2858
- );
2859
3117
  return hasAttrs;
2860
3118
  }
2861
3119
  #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }, constraintExpr) {
@@ -2889,9 +3147,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2889
3147
  const isRepeated = attrTag.length > 1;
2890
3148
  const [firstAttrTag] = attrTag;
2891
3149
  const name = this.#getAttrTagName(firstAttrTag);
2892
- this.#extractor.write(`["${name}"`);
2893
- this.#writeTagNameComment(firstAttrTag);
2894
- this.#extractor.write("]: ");
3150
+ this.#extractor.write(`["`).anchor(firstAttrTag.name).write(`${name}"]: `);
2895
3151
  if (isRepeated) {
2896
3152
  const templateVar = this.#getTemplateVar(firstAttrTag.owner);
2897
3153
  if (templateVar) {
@@ -2903,9 +3159,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2903
3159
  }
2904
3160
  this.#extractor.write(`"${name}",`);
2905
3161
  for (const childNode of attrTag) {
2906
- this.#extractor.write(`{["${name}"`);
2907
- this.#writeTagNameComment(childNode);
2908
- this.#extractor.write("]: ");
3162
+ this.#extractor.write(`{["`).anchor(childNode.name).write(`${name}"]: `);
2909
3163
  this.#writeTagInputObject(childNode);
2910
3164
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2911
3165
  }
@@ -2951,11 +3205,8 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2951
3205
  break;
2952
3206
  }
2953
3207
  case "for": {
2954
- this.#extractor.write(
2955
- `${varShared(getForAttrTagRuntime(this.#parsed, tag))}({
2956
- `
2957
- );
2958
- this.#writeTagNameComment(tag);
3208
+ this.#extractor.write(`${varShared(getForAttrTagRuntime(this.#parsed, tag))}({
3209
+ `).anchor(tag.name);
2959
3210
  this.#writeAttrs(tag);
2960
3211
  this.#extractor.write("\n}, \n");
2961
3212
  this.#writeComments(tag);
@@ -3029,7 +3280,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3029
3280
  hasBodyContent = true;
3030
3281
  }
3031
3282
  if (tag.params || hasBodyContent) {
3032
- this.#extractor.write("[");
3283
+ this.#extractor.write("[").anchor(tag.name);
3033
3284
  if (this.#interop) {
3034
3285
  const templateVar = this.#getTemplateVar(
3035
3286
  tag.type === 16 /* AttrTag */ ? tag.owner : tag
@@ -3042,7 +3293,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3042
3293
  } else {
3043
3294
  this.#extractor.write('"content"');
3044
3295
  }
3045
- this.#writeTagNameComment(tag);
3046
3296
  this.#extractor.write("]: ");
3047
3297
  if (tag.params) {
3048
3298
  this.#extractor.write("(");
@@ -3074,10 +3324,10 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3074
3324
  this.#extractor.write(SEP_COMMA_NEW_LINE);
3075
3325
  }
3076
3326
  if (tag.type === 16 /* AttrTag */) {
3077
- this.#extractor.write("[/*").copy(tag.name).write(`*/Symbol.iterator]: ${varShared("any")}${SEP_COMMA_NEW_LINE}`);
3327
+ this.#extractor.write("[").anchor(tag.name).write(`Symbol.iterator]: ${varShared("any")}${SEP_COMMA_NEW_LINE}`);
3078
3328
  }
3079
3329
  if (!hasInput) {
3080
- this.#writeTagNameComment(tag);
3330
+ this.#extractor.anchor(tag.name);
3081
3331
  }
3082
3332
  if (writeInputObj) {
3083
3333
  this.#extractor.write("\n}");
@@ -3116,25 +3366,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3116
3366
  minIndex = maxIndex + 1;
3117
3367
  } while (true);
3118
3368
  }
3119
- #copyWhitespaceWithin(start, end) {
3120
- const code = this.#code;
3121
- const max = Math.min(end, code.length);
3122
- let lastPos = start;
3123
- let pos = start;
3124
- while (pos < max) {
3125
- if (!isWhitespaceCode(code.charCodeAt(pos))) {
3126
- lastPos = pos + 1;
3127
- if (pos > lastPos) {
3128
- this.#extractor.copy({ start: lastPos, end: pos });
3129
- }
3130
- return;
3131
- }
3132
- pos++;
3133
- }
3134
- if (pos > lastPos) {
3135
- this.#extractor.copy({ start: lastPos, end: pos });
3136
- }
3137
- }
3138
3369
  #processBody(parent) {
3139
3370
  var _a;
3140
3371
  const { body } = parent;
@@ -3349,8 +3580,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3349
3580
  }
3350
3581
  #getJSDocInputTypeFromNodes(nodes) {
3351
3582
  for (const node of nodes) {
3352
- const code = this.#read(node);
3353
- code;
3354
3583
  const info = this.#getJSDocInputTypeFromNode(node);
3355
3584
  if (info) return info;
3356
3585
  }
@@ -3397,10 +3626,23 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3397
3626
  }
3398
3627
  return id;
3399
3628
  }
3400
- #getScopeExpression(body) {
3629
+ #hasScopeExpression(body) {
3630
+ return !!(getHoistSources(body) || this.#getBodyHoistScopeExpression(body));
3631
+ }
3632
+ #writeScopeExpression(body) {
3401
3633
  const sources = getHoistSources(body);
3402
3634
  const hoists = this.#getBodyHoistScopeExpression(body);
3403
- return sources ? `{ ${hoists ? `...${hoists}, ` : ""}${sources.join(SEP_COMMA_SPACE)} }` : hoists;
3635
+ if (!sources) {
3636
+ if (hoists) this.#extractor.write(hoists);
3637
+ return;
3638
+ }
3639
+ this.#extractor.write(`{ ${hoists ? `...${hoists}, ` : ""}`);
3640
+ let sep = SEP_EMPTY;
3641
+ for (const binding of sources) {
3642
+ this.#extractor.write(sep).copy(binding.range);
3643
+ sep = SEP_COMMA_SPACE;
3644
+ }
3645
+ this.#extractor.write(" }");
3404
3646
  }
3405
3647
  #getBodyHoistScopeExpression(body) {
3406
3648
  let hoistVars;
@@ -3659,8 +3901,8 @@ function extractStyle(opts) {
3659
3901
  attr.type === 10 /* AttrNamed */ && ((_a = attr.value) == null ? void 0 : _a.type) === 13 /* AttrValue */ && /^['"]$/.test(code[attr.value.value.start])
3660
3902
  ) {
3661
3903
  const name = read(attr.name);
3662
- if (name === "#style" || name === "style" && node.nameText && name === "style" && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html)) {
3663
- getExtractor("css").write(":root{").copy({
3904
+ if (name === "#style" || name === "style" && node.nameText && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html)) {
3905
+ getExtractor(".css").write(":root{").copy({
3664
3906
  start: attr.value.value.start + 1,
3665
3907
  end: attr.value.value.end - 1
3666
3908
  }).write("}");