marko 6.3.33 → 6.3.35

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.
Files changed (69) hide show
  1. package/cheatsheet.md +37 -33
  2. package/dist/common/constants/accessor-prefix.d.ts +1 -0
  3. package/dist/common/constants/accessor-prefix.debug.d.ts +1 -0
  4. package/dist/common/errors.d.ts +2 -0
  5. package/dist/common/types.d.ts +10 -0
  6. package/dist/debug/dom/catch.feat.js +1 -1
  7. package/dist/debug/dom/catch.feat.mjs +1 -1
  8. package/dist/debug/dom/controllable-input.feat.js +1 -1
  9. package/dist/debug/dom/controllable-input.feat.mjs +1 -1
  10. package/dist/debug/dom/controllable-open.feat.js +1 -1
  11. package/dist/debug/dom/controllable-open.feat.mjs +1 -1
  12. package/dist/debug/dom/controllable-select.feat.js +1 -1
  13. package/dist/debug/dom/controllable-select.feat.mjs +1 -1
  14. package/dist/debug/dom/controllable-textarea.feat.js +1 -1
  15. package/dist/debug/dom/controllable-textarea.feat.mjs +1 -1
  16. package/dist/debug/dom/controllable.feat.js +1 -1
  17. package/dist/debug/dom/controllable.feat.mjs +1 -1
  18. package/dist/debug/{dom-BJ93mcSe.mjs → dom-B57LrRnX.mjs} +89 -46
  19. package/dist/debug/{dom-CiFITSPN.js → dom-Bt4OoZ-j.js} +89 -46
  20. package/dist/debug/dom.js +3 -1
  21. package/dist/debug/dom.mjs +3 -1
  22. package/dist/debug/html.js +205 -98
  23. package/dist/debug/html.mjs +205 -98
  24. package/dist/dom/catch.feat.js +1 -1
  25. package/dist/dom/catch.feat.mjs +1 -1
  26. package/dist/dom/control-flow.d.ts +4 -1
  27. package/dist/dom/controllable-input.feat.js +1 -1
  28. package/dist/dom/controllable-input.feat.mjs +1 -1
  29. package/dist/dom/controllable-open.feat.js +1 -1
  30. package/dist/dom/controllable-open.feat.mjs +1 -1
  31. package/dist/dom/controllable-select.feat.js +1 -1
  32. package/dist/dom/controllable-select.feat.mjs +1 -1
  33. package/dist/dom/controllable-textarea.feat.js +1 -1
  34. package/dist/dom/controllable-textarea.feat.mjs +1 -1
  35. package/dist/dom/controllable.feat.js +1 -1
  36. package/dist/dom/controllable.feat.mjs +1 -1
  37. package/dist/dom/signals.d.ts +3 -3
  38. package/dist/{dom-Cj4HQ7T_.mjs → dom-BP2XSglG.mjs} +46 -33
  39. package/dist/{dom-CI-06TZb.js → dom-BeF9xIzO.js} +46 -33
  40. package/dist/dom.js +3 -1
  41. package/dist/dom.mjs +3 -1
  42. package/dist/html/compat.d.ts +4 -2
  43. package/dist/html/dynamic-tag.d.ts +1 -1
  44. package/dist/html/serializer.d.ts +9 -1
  45. package/dist/html/template.d.ts +1 -0
  46. package/dist/html/writer.d.ts +1 -0
  47. package/dist/html.js +88 -63
  48. package/dist/html.mjs +88 -63
  49. package/dist/translator/core/client.d.ts +1 -2
  50. package/dist/translator/core/server.d.ts +1 -2
  51. package/dist/translator/core/static.d.ts +1 -2
  52. package/dist/translator/index.js +514 -314
  53. package/dist/translator/util/constants/binding-type.d.ts +1 -0
  54. package/dist/translator/util/references.d.ts +8 -1
  55. package/dist/translator/util/serialize-reasons.d.ts +4 -4
  56. package/dist/translator/util/signals.d.ts +5 -0
  57. package/dist/translator/util/statement-tag.d.ts +2 -0
  58. package/dist/translator/util/translate-var.d.ts +1 -1
  59. package/dist/translator/visitors/export-declaration.d.ts +8 -0
  60. package/dist/translator/visitors/program/index.d.ts +0 -1
  61. package/package.json +5 -4
  62. package/tags/html-comment.d.marko +2 -0
  63. package/tags/html-script.d.marko +2 -0
  64. package/tags/html-style.d.marko +2 -0
  65. package/tags/let.d.marko +4 -5
  66. package/tags/show.d.marko +6 -0
  67. package/tags/try.d.marko +1 -1
  68. package/tags-html.d.ts +6 -1
  69. /package/dist/translator/util/{get-accessor-char.d.ts → get-accessor-enums.d.ts} +0 -0
@@ -52,10 +52,21 @@ var runtime_info_default = {
52
52
  };
53
53
  //#endregion
54
54
  //#region src/translator/util/assert.ts
55
+ const docsAnchors = {
56
+ if: "if--else",
57
+ "else-if": "if--else",
58
+ else: "if--else",
59
+ effect: "",
60
+ attrs: ""
61
+ };
62
+ function coreTagDocsURL(tagName) {
63
+ const anchor = docsAnchors[tagName] ?? tagName;
64
+ return `https://markojs.com/docs/reference/core-tag${anchor && "#" + anchor}`;
65
+ }
55
66
  function assertNoSpreadAttrs(tag) {
56
67
  for (const attr of tag.get("attributes")) if (attr.isMarkoSpreadAttribute()) {
57
68
  const tagName = tag.get("name").node.value;
58
- throw attr.buildCodeFrameError(`The [\`<${tagName}>\`](https://markojs.com/docs/reference/core-tag#${tagName}) tag does not support \`...spread\` attributes.`);
69
+ throw attr.buildCodeFrameError(`The [\`<${tagName}>\`](${coreTagDocsURL(tagName)}) tag does not support \`...spread\` attributes.`);
59
70
  }
60
71
  }
61
72
  function assertNoTagVarMutation(tag) {
@@ -71,7 +82,7 @@ function assertNoBodyContent(tag) {
71
82
  if (tag.node.body.body.length) {
72
83
  const tagName = tag.get("name");
73
84
  const tagNameLiteral = tagName.node.value;
74
- throw tagName.buildCodeFrameError(`The [\`<${tagNameLiteral}>\`](https://markojs.com/docs/reference/core-tag#${tagNameLiteral}) tag does not support body content.`);
85
+ throw tagName.buildCodeFrameError(`The [\`<${tagNameLiteral}>\`](${coreTagDocsURL(tagNameLiteral)}) tag does not support body content.`);
75
86
  }
76
87
  }
77
88
  //#endregion
@@ -115,6 +126,7 @@ var accessor_prefix_debug_exports = /* @__PURE__ */ __exportAll({
115
126
  ControlledValue: () => ControlledValue$1,
116
127
  DynamicHTMLLastChild: () => DynamicHTMLLastChild$1,
117
128
  EventAttributes: () => EventAttributes$1,
129
+ IdFallback: () => IdFallback$1,
118
130
  KeyedScopes: () => KeyedScopes$1,
119
131
  Lifecycle: () => Lifecycle$1,
120
132
  Promise: () => Promise$2,
@@ -130,6 +142,7 @@ const ControlledType$1 = "ControlledType:";
130
142
  const ControlledValue$1 = "ControlledValue:";
131
143
  const DynamicHTMLLastChild$1 = "DynamicHTMLLastChild:";
132
144
  const EventAttributes$1 = "EventAttributes:";
145
+ const IdFallback$1 = "IdFallback:";
133
146
  const KeyedScopes$1 = "KeyedScopes:";
134
147
  const Lifecycle$1 = "Lifecycle:";
135
148
  const Promise$2 = "Promise:";
@@ -192,6 +205,7 @@ const StartNode$1 = "#StartNode";
192
205
  const Subscriptions$1 = "#Subscriptions";
193
206
  const TagVariable$1 = "#TagVariable";
194
207
  const TagVariableChange$2 = "#TagVariableChange";
208
+ const Owner$1 = "owner";
195
209
  //#endregion
196
210
  //#region src/translator/util/evaluate.ts
197
211
  function evaluate(value) {
@@ -601,7 +615,7 @@ function getTagName(tag) {
601
615
  switch (tag.node.name.type) {
602
616
  case "StringLiteral": return tag.node.name.value;
603
617
  case "TemplateLiteral":
604
- if (tag.node.name.quasis.length === 1) return tag.node.name.quasis[0].value.raw;
618
+ if (tag.node.name.quasis.length === 1) return tag.node.name.quasis[0].value.cooked;
605
619
  break;
606
620
  }
607
621
  }
@@ -728,12 +742,8 @@ var Sorted = class {
728
742
  if (!Array.isArray(subset)) return this.findIndex(superset, subset) !== -1;
729
743
  if (!Array.isArray(superset)) return false;
730
744
  const subLen = subset.length;
731
- const supLen = superset.length;
732
- if (subLen > supLen) return false;
733
- for (let i = subLen; i--;) {
734
- const found = findIndexSorted(this.compare, superset, subset[i]);
735
- if (found === -1 || supLen - found <= i) return false;
736
- }
745
+ if (subLen > superset.length) return false;
746
+ for (let i = subLen; i--;) if (findIndexSorted(this.compare, superset, subset[i]) < i) return false;
737
747
  return true;
738
748
  }
739
749
  };
@@ -926,6 +936,7 @@ var accessor_prefix_exports = /* @__PURE__ */ __exportAll({
926
936
  ControlledValue: () => "G",
927
937
  DynamicHTMLLastChild: () => "H",
928
938
  EventAttributes: () => "I",
939
+ IdFallback: () => "J",
929
940
  KeyedScopes: () => "O",
930
941
  Lifecycle: () => "K",
931
942
  Promise: () => "L",
@@ -983,7 +994,7 @@ function getReadyId(file = (0, _marko_compiler_babel_utils.getFile)()) {
983
994
  return (markoOpts.optimize ? "_" : "ready:") + (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, file.opts.filename);
984
995
  }
985
996
  //#endregion
986
- //#region src/translator/util/get-accessor-char.ts
997
+ //#region src/translator/util/get-accessor-enums.ts
987
998
  function getAccessorPrefix() {
988
999
  return isOptimize() ? accessor_prefix_exports : accessor_prefix_debug_exports;
989
1000
  }
@@ -994,6 +1005,8 @@ function getAccessorProp() {
994
1005
  //#region src/translator/util/serialize-reasons.ts
995
1006
  const scopeExprsBySection = /* @__PURE__ */ new WeakMap();
996
1007
  const propExprsBySection = /* @__PURE__ */ new WeakMap();
1008
+ const scopeProvenanceBySection = /* @__PURE__ */ new WeakMap();
1009
+ const propProvenanceBySection = /* @__PURE__ */ new WeakMap();
997
1010
  const serializePropsByBinding = /* @__PURE__ */ new WeakMap();
998
1011
  const serializePropByModifier = {};
999
1012
  function isSameReason(a, b) {
@@ -1003,43 +1016,46 @@ function isForceSerialized(section, prop, prefix) {
1003
1016
  return true === (prop ? section.serializeReasons.get(getPropKey(section, prop, prefix)) : section.serializeReason);
1004
1017
  }
1005
1018
  function addSerializeReason(section, reason, prop, prefix) {
1006
- if (reason) if (prop) {
1007
- const key = getPropKey(section, prop, prefix);
1008
- const curReason = section.serializeReasons.get(key);
1009
- if (curReason !== true) if (reason === true) forcePropSerialize(section, key);
1010
- else {
1011
- const newReason = mergeSerializeReasons(curReason, reason);
1012
- if (curReason !== newReason) setPropSerializeReason(section, key, newReason);
1013
- }
1014
- } else {
1015
- const curReason = section.serializeReason;
1016
- if (curReason !== true) if (reason === true) forceSerialize(section);
1017
- else {
1018
- const newReason = mergeSerializeReasons(curReason, reason);
1019
- if (curReason !== newReason) setSerializeReason(section, newReason);
1019
+ if (reason) {
1020
+ if (reason !== true) addProvenance(section, reason, prop && getPropKey(section, prop, prefix));
1021
+ if (prop) {
1022
+ const key = getPropKey(section, prop, prefix);
1023
+ const curReason = section.serializeReasons.get(key);
1024
+ if (curReason !== true) if (reason === true) forcePropSerialize(section, key);
1025
+ else {
1026
+ const newReason = mergeSerializeReasons(curReason, reason);
1027
+ if (curReason !== newReason) setPropSerializeReason(section, key, newReason);
1028
+ }
1029
+ } else {
1030
+ const curReason = section.serializeReason;
1031
+ if (curReason !== true) if (reason === true) forceSerialize(section);
1032
+ else {
1033
+ const newReason = mergeSerializeReasons(curReason, reason);
1034
+ if (curReason !== newReason) setSerializeReason(section, newReason);
1035
+ }
1020
1036
  }
1021
1037
  }
1022
1038
  }
1023
1039
  function addSerializeExpr(section, expr, prop, prefix) {
1024
- if (expr) {
1025
- if (prop) {
1026
- const key = getPropKey(section, prop, prefix);
1027
- if (section.serializeReasons.get(key) !== true) if (expr === true) forcePropSerialize(section, key);
1040
+ if (expr) if (prop) {
1041
+ const key = getPropKey(section, prop, prefix);
1042
+ if (expr === true) {
1043
+ if (section.serializeReasons.get(key) !== true) forcePropSerialize(section, key);
1044
+ } else {
1045
+ let curExpr;
1046
+ let curExprs = propExprsBySection.get(section);
1047
+ if (curExprs) curExpr = curExprs.get(key);
1028
1048
  else {
1029
- let curExpr;
1030
- let curExprs = propExprsBySection.get(section);
1031
- if (curExprs) curExpr = curExprs.get(key);
1032
- else {
1033
- curExprs = /* @__PURE__ */ new Map();
1034
- propExprsBySection.set(section, curExprs);
1035
- }
1036
- curExprs.set(key, curExpr ? concat(curExpr, expr) : expr);
1049
+ curExprs = /* @__PURE__ */ new Map();
1050
+ propExprsBySection.set(section, curExprs);
1037
1051
  }
1038
- } else if (section.serializeReason !== true) if (expr === true) forceSerialize(section);
1039
- else {
1040
- const curExpr = scopeExprsBySection.get(section);
1041
- scopeExprsBySection.set(section, curExpr ? concat(curExpr, expr) : expr);
1052
+ curExprs.set(key, curExpr ? concat(curExpr, expr) : expr);
1042
1053
  }
1054
+ } else if (expr === true) {
1055
+ if (section.serializeReason !== true) forceSerialize(section);
1056
+ } else {
1057
+ const curExpr = scopeExprsBySection.get(section);
1058
+ scopeExprsBySection.set(section, curExpr ? concat(curExpr, expr) : expr);
1043
1059
  }
1044
1060
  }
1045
1061
  function addOwnerSerializeReason(from, to, reason) {
@@ -1093,6 +1109,7 @@ function applySerializeExprs(section) {
1093
1109
  if (propExprs) {
1094
1110
  propExprsBySection.delete(section);
1095
1111
  for (const [key, exprs] of propExprs) {
1112
+ addProvenance(section, getProvenanceForExprs(exprs), key);
1096
1113
  const exprReason = getSerializeSourcesForExprs(exprs);
1097
1114
  if (exprReason) {
1098
1115
  const curReason = section.serializeReasons.get(key);
@@ -1103,8 +1120,9 @@ function applySerializeExprs(section) {
1103
1120
  }
1104
1121
  const scopeExprs = scopeExprsBySection.get(section);
1105
1122
  if (scopeExprs) {
1106
- const exprReason = getSerializeSourcesForExprs(scopeExprs);
1107
1123
  scopeExprsBySection.delete(section);
1124
+ addProvenance(section, getProvenanceForExprs(scopeExprs));
1125
+ const exprReason = getSerializeSourcesForExprs(scopeExprs);
1108
1126
  if (exprReason) {
1109
1127
  const curReason = section.serializeReason;
1110
1128
  const newReason = mergeSerializeReasons(curReason, exprReason);
@@ -1125,6 +1143,26 @@ function finalizeSerializeReason(section) {
1125
1143
  }
1126
1144
  if (newReason && curReason !== newReason) setSerializeReason(section, newReason);
1127
1145
  }
1146
+ const propProvenance = propProvenanceBySection.get(section);
1147
+ if (propProvenance) for (const provenance of propProvenance.values()) addProvenance(section, provenance);
1148
+ }
1149
+ function addProvenance(section, sources, key) {
1150
+ if (!sources) return;
1151
+ if (key) {
1152
+ let provenance = propProvenanceBySection.get(section);
1153
+ if (!provenance) propProvenanceBySection.set(section, provenance = /* @__PURE__ */ new Map());
1154
+ provenance.set(key, mergeSources(provenance.get(key), sources));
1155
+ } else scopeProvenanceBySection.set(section, mergeSources(scopeProvenanceBySection.get(section), sources));
1156
+ }
1157
+ function getProvenanceForExprs(exprs) {
1158
+ let sources;
1159
+ forEach(exprs, (expr) => {
1160
+ sources = mergeSources(sources, getSerializeSourcesForExpr(expr));
1161
+ forEach(expr.referencedBindingsInFunction, (binding) => {
1162
+ sources = mergeSources(sources, getSerializeSourcesForRef(binding));
1163
+ });
1164
+ });
1165
+ return sources;
1128
1166
  }
1129
1167
  function getPropKey(section, prop, prefix) {
1130
1168
  if (isStrOrSym(prop)) {
@@ -1142,12 +1180,10 @@ function getPropKey(section, prop, prefix) {
1142
1180
  }
1143
1181
  }
1144
1182
  function forceSerialize(section) {
1145
- scopeExprsBySection.delete(section);
1146
1183
  setSerializeReason(section, true);
1147
1184
  }
1148
1185
  function forcePropSerialize(section, key) {
1149
1186
  setPropSerializeReason(section, key, true);
1150
- propExprsBySection.get(section)?.delete(key);
1151
1187
  }
1152
1188
  function isStrOrSym(v) {
1153
1189
  switch (typeof v) {
@@ -1544,8 +1580,23 @@ var function_default = { analyze(fn) {
1544
1580
  if (refs === true) registerFunction(fnExtra, true);
1545
1581
  else if (refs.size) getReferencesByFn().set(fnExtra, refs);
1546
1582
  } else if (shouldAlwaysRegister(markoRoot)) registerFunction(fnExtra, true);
1547
- else getReferencesByFn().set(fnExtra, /* @__PURE__ */ new Set([exprRoot.node.extra ??= {}]));
1583
+ else {
1584
+ const refs = /* @__PURE__ */ new Set([exprRoot.node.extra ??= {}]);
1585
+ if (getConstTagVarRefs(markoRoot, refs) === true) registerFunction(fnExtra, true);
1586
+ else getReferencesByFn().set(fnExtra, refs);
1587
+ }
1548
1588
  } };
1589
+ function getConstTagVarRefs(markoRoot, refs, seen = /* @__PURE__ */ new Set()) {
1590
+ const tag = getTagFromMarkoRoot(markoRoot);
1591
+ if (!tag?.node.var || !isCoreTagName(tag, "const") || seen.has(tag.node)) return refs;
1592
+ seen.add(tag.node);
1593
+ const ids = tag.get("var").getOuterBindingIdentifiers();
1594
+ for (const name in ids) {
1595
+ const binding = tag.scope.getBinding(name);
1596
+ if (binding && addBindingRefs(binding, refs, seen) === true) return true;
1597
+ }
1598
+ return refs;
1599
+ }
1549
1600
  function finalizeFunctionRegistry() {
1550
1601
  for (const [fnExtra, exprExtras] of getReferencesByFn()) {
1551
1602
  const reason = resolveSerializeReason(exprExtras);
@@ -1676,7 +1727,10 @@ function addBindingRefs(binding, refs, seen) {
1676
1727
  if (isStaticRoot(markoRoot)) {
1677
1728
  if (getStaticDeclRefs(ref, refs, seen) === true) return true;
1678
1729
  } else if (shouldAlwaysRegister(markoRoot)) return true;
1679
- else refs.add(exprRoot.node.extra ??= {});
1730
+ else {
1731
+ refs.add(exprRoot.node.extra ??= {});
1732
+ if (getConstTagVarRefs(markoRoot, refs, seen) === true) return true;
1733
+ }
1680
1734
  }
1681
1735
  }
1682
1736
  function shouldAlwaysRegister(markoRoot) {
@@ -1887,7 +1941,10 @@ function assertExclusiveAttrs(attrs, onError = throwErr) {
1887
1941
  (exclusiveAttrs ||= []).push("checkedValueChange");
1888
1942
  if ("checked" in attrs) exclusiveAttrs.push("checked");
1889
1943
  }
1890
- if (attrs.valueChange) (exclusiveAttrs ||= []).push("valueChange");
1944
+ if (attrs.valueChange) {
1945
+ (exclusiveAttrs ||= []).push("valueChange");
1946
+ if ("checked" in attrs && !exclusiveAttrs.includes("checked")) exclusiveAttrs.push("checked");
1947
+ }
1891
1948
  if (exclusiveAttrs && exclusiveAttrs.length > 1) onError(`The attributes ${joinWithAnd(exclusiveAttrs)} are mutually exclusive.`);
1892
1949
  }
1893
1950
  }
@@ -1907,8 +1964,8 @@ function joinWithAnd(a) {
1907
1964
  function _unescaped(val) {
1908
1965
  return val ? val + "" : val === 0 ? "0" : "";
1909
1966
  }
1910
- const unsafeXMLReg = /[<&]/g;
1911
- const replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;";
1967
+ const unsafeXMLReg = /[<&\r]/g;
1968
+ const replaceUnsafeXML = (c) => c === "&" ? "&amp;" : c === "<" ? "&lt;" : "&#13;";
1912
1969
  const escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str;
1913
1970
  function _escape(val) {
1914
1971
  return val ? escapeXMLStr(val + "") : val === 0 ? "0" : "";
@@ -1937,6 +1994,9 @@ function getContext(key) {
1937
1994
  function getState() {
1938
1995
  return $chunk.boundary.state;
1939
1996
  }
1997
+ function rendererKey(renderer) {
1998
+ return renderer?.["owner"] === void 0 ? renderer?.["id"] || renderer : renderer["id"] + " " + renderer[Owner$1];
1999
+ }
1940
2000
  function getScopeById(scopeId) {
1941
2001
  if (scopeId !== void 0) return $chunk.boundary.state.scopes.get(scopeId);
1942
2002
  }
@@ -2031,7 +2091,7 @@ function _attr_textarea_value(scopeId, nodeAccessor, value, valueChange, seriali
2031
2091
  }
2032
2092
  function _textarea_value(value) {
2033
2093
  const escaped = _escape(normalizeStrAttrValue(value));
2034
- return escaped[0] === "\n" || escaped[0] === "\r" ? "\n" + escaped : escaped;
2094
+ return escaped[0] === "\n" ? "\n" + escaped : escaped;
2035
2095
  }
2036
2096
  function _attr_input_value(scopeId, nodeAccessor, value, valueChange, serializeType) {
2037
2097
  if (valueChange) writeControlledScope(2, scopeId, nodeAccessor, void 0, valueChange, serializeType);
@@ -2143,8 +2203,8 @@ function nonVoidAttr(name, value) {
2143
2203
  }
2144
2204
  return " " + name + attrAssignment(value + "");
2145
2205
  }
2146
- const singleQuoteAttrReplacements = /'|&(?=[#a-zA-Z])/g;
2147
- const doubleQuoteAttrReplacements = /"|&(?=[#a-zA-Z])/g;
2206
+ const singleQuoteAttrReplacements = /['\r]|&(?=[#a-zA-Z])/g;
2207
+ const doubleQuoteAttrReplacements = /["\r]|&(?=[#a-zA-Z])/g;
2148
2208
  const needsQuotedAttr = /["'>\s]|&[#a-zA-Z]|\/$/g;
2149
2209
  function attrAssignment(value) {
2150
2210
  return value ? needsQuotedAttr.test(value) ? value[needsQuotedAttr.lastIndex - 1] === (needsQuotedAttr.lastIndex = 0, "\"") ? "='" + escapeSingleQuotedAttrValue(value) + "'" : "=\"" + escapeDoubleQuotedAttrValue(value) + "\"" : "=" + value : "";
@@ -2153,13 +2213,13 @@ function escapeSingleQuotedAttrValue(value) {
2153
2213
  return singleQuoteAttrReplacements.test(value) ? value.replace(singleQuoteAttrReplacements, replaceUnsafeSingleQuoteAttrChar) : value;
2154
2214
  }
2155
2215
  function replaceUnsafeSingleQuoteAttrChar(match) {
2156
- return match === "'" ? "&#39;" : "&amp;";
2216
+ return match === "'" ? "&#39;" : match === "\r" ? "&#13;" : "&amp;";
2157
2217
  }
2158
2218
  function escapeDoubleQuotedAttrValue(value) {
2159
2219
  return doubleQuoteAttrReplacements.test(value) ? value.replace(doubleQuoteAttrReplacements, replaceUnsafeDoubleQuoteAttrChar) : value;
2160
2220
  }
2161
2221
  function replaceUnsafeDoubleQuoteAttrChar(match) {
2162
- return match === "\"" ? "&#34;" : "&amp;";
2222
+ return match === "\"" ? "&#34;" : match === "\r" ? "&#13;" : "&amp;";
2163
2223
  }
2164
2224
  function normalizedValueMatches(a, b) {
2165
2225
  const value = normalizeStrAttrValue(b);
@@ -2226,7 +2286,7 @@ let _dynamic_tag = (scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, s
2226
2286
  }
2227
2287
  }
2228
2288
  if (rendered) {
2229
- if (shouldResume) writeScope(scopeId, { [ConditionalRenderer$1 + accessor]: renderer?.["id"] || renderer });
2289
+ if (shouldResume) writeScope(scopeId, { [ConditionalRenderer$1 + accessor]: rendererKey(renderer) });
2230
2290
  } else _scope_id();
2231
2291
  return result;
2232
2292
  };
@@ -2690,6 +2750,17 @@ var return_default = {
2690
2750
  (0, _marko_compiler_babel_utils.assertNoParams)(tag);
2691
2751
  assertNoBodyContent(tag);
2692
2752
  (0, _marko_compiler_babel_utils.assertAllowedAttributes)(tag, ["value", "valueChange"]);
2753
+ let valueAttr;
2754
+ let valueChangeAttr;
2755
+ for (const attr of tag.node.attributes) if (_marko_compiler.types.isMarkoAttribute(attr)) {
2756
+ if (attr.name === "value") {
2757
+ if (valueAttr) throw tag.hub.buildError(attr, "Invalid duplicate value attribute.");
2758
+ valueAttr = attr;
2759
+ } else if (attr.name === "valueChange") {
2760
+ if (valueChangeAttr) throw tag.hub.buildError(attr, "Invalid duplicate valueChange attribute.");
2761
+ valueChangeAttr = attr;
2762
+ }
2763
+ }
2693
2764
  const parentTag = getParentTag(tag);
2694
2765
  if (parentTag) {
2695
2766
  if ((0, _marko_compiler_babel_utils.isNativeTag)(parentTag)) throw tag.get("name").buildCodeFrameError("The [`<return>` tag](https://markojs.com/docs/reference/core-tag#return) can not be used in a [native tag](https://markojs.com/docs/reference/native-tag).");
@@ -2951,10 +3022,25 @@ function setSectionSerializedValue(section, prop, expression) {
2951
3022
  }
2952
3023
  function setBindingSerializedValue(section, binding, expression, prefix) {
2953
3024
  const reason = getSerializeReason(section, binding, prefix);
2954
- if (reason) getSerializedAccessors(section).set(prefix === void 0 ? getScopeAccessor(binding) : getPrefixedScopeAccessor(binding, prefix), {
3025
+ if (reason) if (prefix === void 0) getSerializedAccessors(section).set(getScopeAccessor(binding), {
2955
3026
  expression,
2956
3027
  reason
2957
3028
  });
3029
+ else {
3030
+ const accessor = getPrefixedScopeAccessor(binding, prefix);
3031
+ getSerializedAccessors(section).set(accessor, {
3032
+ expression,
3033
+ reason
3034
+ });
3035
+ if (!isOptimize() && prefix === getAccessorPrefix().TagVariableChange) {
3036
+ const { root, access } = getDebugScopeAccess(binding);
3037
+ setSectionDebugVar(section, accessor, `${root.name + access}Change`, root.loc);
3038
+ }
3039
+ }
3040
+ }
3041
+ const [getSectionDebugVars] = createSectionState("sectionDebugVars", () => /* @__PURE__ */ new Map());
3042
+ function setSectionDebugVar(section, accessor, name, loc) {
3043
+ if (!isOptimize()) getSectionDebugVars(section).set(accessor, loc ? [name, `${loc.start.line}:${loc.start.column + 1}`] : [name]);
2958
3044
  }
2959
3045
  const nonAnalyzedForceSerializedSection = /* @__PURE__ */ new WeakSet();
2960
3046
  function setSerializedValue(section, key, expression) {
@@ -2998,6 +3084,7 @@ function getSignal(section, referencedBindings, name) {
2998
3084
  section,
2999
3085
  values: [],
3000
3086
  intersection: void 0,
3087
+ forwards: void 0,
3001
3088
  render: [],
3002
3089
  effect: [],
3003
3090
  hasHTMLEffect: false,
@@ -3074,12 +3161,13 @@ function isPureMemberForwarder(binding) {
3074
3161
  for (const alias of binding.propertyAliases.values()) if (alias.type !== 6) return true;
3075
3162
  return false;
3076
3163
  }
3077
- function pushMemberForwards(renderStatements, value, alias) {
3164
+ function pushMemberForwards(signal, value, alias) {
3078
3165
  if (isPureMemberForwarder(alias)) {
3079
- for (const [key, child] of alias.propertyAliases) if (child.type !== 6) pushMemberForwards(renderStatements, toMemberExpression(_marko_compiler.types.cloneNode(value, true), key, alias.nullable), child);
3166
+ for (const [key, child] of alias.propertyAliases) if (child.type !== 6) pushMemberForwards(signal, toMemberExpression(_marko_compiler.types.cloneNode(value, true), key, alias.nullable), child);
3080
3167
  } else {
3081
3168
  const aliasSignal = getSignal(alias.section, alias);
3082
- renderStatements.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3169
+ signal.forwards = push(signal.forwards, aliasSignal);
3170
+ signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3083
3171
  scopeIdentifier,
3084
3172
  value,
3085
3173
  ...getTranslatedExtraArgs(aliasSignal)
@@ -3094,32 +3182,35 @@ function getSignalFn(signal) {
3094
3182
  if (isValue) {
3095
3183
  for (const alias of binding.aliases) {
3096
3184
  const aliasSignal = getSignal(alias.section, alias);
3097
- if (signalHasStatements(aliasSignal)) if (alias.excludeProperties !== void 0) {
3098
- const aliasId = _marko_compiler.types.identifier(alias.name);
3099
- let pattern;
3100
- if (alias.restOffset) pattern = _marko_compiler.types.arrayPattern(new Array(alias.restOffset).fill(null).concat(_marko_compiler.types.restElement(aliasId)));
3101
- else {
3102
- const props = [];
3103
- forEach(alias.excludeProperties, (name) => {
3104
- const propId = toPropertyName(name);
3105
- const shorthand = propId.type === "Identifier" && _marko_compiler.types.isValidIdentifier(name);
3106
- props.push(_marko_compiler.types.objectProperty(propId, shorthand ? propId : generateUidIdentifier(name), false, shorthand));
3107
- });
3108
- props.push(_marko_compiler.types.restElement(aliasId));
3109
- pattern = _marko_compiler.types.objectPattern(props);
3110
- }
3111
- signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([pattern], _marko_compiler.types.callExpression(aliasSignal.identifier, [
3185
+ if (signalHasStatements(aliasSignal)) {
3186
+ signal.forwards = push(signal.forwards, aliasSignal);
3187
+ if (alias.excludeProperties !== void 0) {
3188
+ const aliasId = _marko_compiler.types.identifier(alias.name);
3189
+ let pattern;
3190
+ if (alias.restOffset) pattern = _marko_compiler.types.arrayPattern(new Array(alias.restOffset).fill(null).concat(_marko_compiler.types.restElement(aliasId)));
3191
+ else {
3192
+ const props = [];
3193
+ forEach(alias.excludeProperties, (name) => {
3194
+ const propId = toPropertyName(name);
3195
+ const shorthand = propId.type === "Identifier" && _marko_compiler.types.isValidIdentifier(name);
3196
+ props.push(_marko_compiler.types.objectProperty(propId, shorthand ? propId : generateUidIdentifier(name), false, shorthand));
3197
+ });
3198
+ props.push(_marko_compiler.types.restElement(aliasId));
3199
+ pattern = _marko_compiler.types.objectPattern(props);
3200
+ }
3201
+ signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([pattern], _marko_compiler.types.callExpression(aliasSignal.identifier, [
3202
+ scopeIdentifier,
3203
+ aliasId,
3204
+ ...getTranslatedExtraArgs(aliasSignal)
3205
+ ])), [binding.nullable ? _marko_compiler.types.logicalExpression("||", createScopeReadExpression(binding), alias.restOffset ? _marko_compiler.types.arrayExpression([]) : _marko_compiler.types.objectExpression([])) : createScopeReadExpression(binding)])));
3206
+ } else signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3112
3207
  scopeIdentifier,
3113
- aliasId,
3208
+ createScopeReadExpression(binding),
3114
3209
  ...getTranslatedExtraArgs(aliasSignal)
3115
- ])), [binding.nullable ? _marko_compiler.types.logicalExpression("||", createScopeReadExpression(binding), alias.restOffset ? _marko_compiler.types.arrayExpression([]) : _marko_compiler.types.objectExpression([])) : createScopeReadExpression(binding)])));
3116
- } else signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3117
- scopeIdentifier,
3118
- createScopeReadExpression(binding),
3119
- ...getTranslatedExtraArgs(aliasSignal)
3120
- ])));
3210
+ ])));
3211
+ }
3121
3212
  }
3122
- for (const [key, alias] of binding.propertyAliases) if (alias.type !== 6) pushMemberForwards(signal.render, toMemberExpression(createScopeReadExpression(binding), key, binding.nullable), alias);
3213
+ for (const [key, alias] of binding.propertyAliases) if (alias.type !== 6) pushMemberForwards(signal, toMemberExpression(createScopeReadExpression(binding), key, binding.nullable), alias);
3123
3214
  if (assertsHoists) signal.render.push(_marko_compiler.types.expressionStatement(callRuntime("_assert_hoist", createScopeReadExpression(binding))));
3124
3215
  }
3125
3216
  for (const value of signal.values) {
@@ -3255,9 +3346,9 @@ function addValue(targetSection, referencedBindings, signal, value) {
3255
3346
  }
3256
3347
  function buildResumeRegisterKey(section, referencedBindings, type) {
3257
3348
  let name = "";
3258
- if (referencedBindings) if (typeof referencedBindings === "string") name += `_${referencedBindings}`;
3259
- else if (Array.isArray(referencedBindings)) for (const ref of referencedBindings) name += `_${ref.name}`;
3260
- else name += `_${referencedBindings.name}`;
3349
+ if (referencedBindings) if (typeof referencedBindings === "string") name += `*${referencedBindings}`;
3350
+ else if (Array.isArray(referencedBindings)) for (const ref of referencedBindings) name += `_${ref.name}#${ref.id}`;
3351
+ else name += `_${referencedBindings.name}#${referencedBindings.id}`;
3261
3352
  return `${section.id}${name}${type ? "/" + type : ""}`;
3262
3353
  }
3263
3354
  function getResumeRegisterId(section, referencedBindings, type) {
@@ -3287,9 +3378,11 @@ function writeSignals(section) {
3287
3378
  let signalDeclaration;
3288
3379
  if (signal.build) {
3289
3380
  let value = signal.build();
3290
- if (!value || !signal.register && _marko_compiler.types.isFunction(value) && _marko_compiler.types.isBlockStatement(value.body) && !value.body.body.length) return;
3381
+ const buildsEagerForward = _marko_compiler.types.isIdentifier(value);
3382
+ if (!value || !signal.register && !signal.referenced && _marko_compiler.types.isFunction(value) && _marko_compiler.types.isBlockStatement(value.body) && !value.body.body.length) return;
3291
3383
  if (_marko_compiler.types.isCallExpression(value)) replaceNullishAndEmptyFunctionsWith0(value.arguments);
3292
3384
  if (signal.register) value = callRuntime("_var_resume", _marko_compiler.types.stringLiteral(getResumeRegisterId(section, signal.referencedBindings, "var")), value);
3385
+ if (buildsEagerForward) forEach(signal.forwards, writeSignal);
3293
3386
  const signalDeclarator = _marko_compiler.types.variableDeclarator(signal.identifier, value);
3294
3387
  signalDeclaration = !section.parent && !signal.referencedBindings && (_marko_compiler.types.isFunctionExpression(value) || _marko_compiler.types.isArrowFunctionExpression(value)) ? _marko_compiler.types.functionDeclaration(signal.identifier, value.params, _marko_compiler.types.isExpression(value.body) ? _marko_compiler.types.blockStatement([_marko_compiler.types.expressionStatement(value.body)]) : value.body) : _marko_compiler.types.variableDeclaration("const", [signalDeclarator]);
3295
3388
  if (signal.export) signalDeclaration = _marko_compiler.types.exportNamedDeclaration(signalDeclaration);
@@ -3333,7 +3426,8 @@ function writeRegisteredFns() {
3333
3426
  params = [localsIdentifier];
3334
3427
  if (registeredFn.referencedBindings || registeredFn.referencesScope) prologue = [_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(scopeIdentifier, _marko_compiler.types.memberExpression(localsIdentifier, _marko_compiler.types.identifier(getAccessorProp().Owner)))])];
3335
3428
  } else params = [scopeIdentifier];
3336
- fn = _marko_compiler.types.functionDeclaration(_marko_compiler.types.identifier(registeredFn.id), params, _marko_compiler.types.blockStatement(toReturnedFunction(registeredFn.node, prologue)));
3429
+ const body = toReturnedFunction(registeredFn.node, prologue);
3430
+ fn = _marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(registeredFn.id), _marko_compiler.types.arrowFunctionExpression(params, body.length === 1 && body[0].type === "ReturnStatement" ? body[0].argument : _marko_compiler.types.blockStatement(body)))]);
3337
3431
  } else if (registeredFn.node.type === "FunctionDeclaration" && registeredFn.node.id?.name === registeredFn.id) fn = registeredFn.node;
3338
3432
  else fn = _marko_compiler.types.functionDeclaration(_marko_compiler.types.identifier(registeredFn.id), registeredFn.node.params, registeredFn.node.body.type === "BlockStatement" ? registeredFn.node.body : _marko_compiler.types.blockStatement([_marko_compiler.types.returnStatement(registeredFn.node.body)]), registeredFn.node.generator, registeredFn.node.async);
3339
3433
  statements.push(fn);
@@ -3439,6 +3533,7 @@ function writeHTMLResumeStatements(path) {
3439
3533
  const writeScopeArgs = [scopeIdIdentifier, _marko_compiler.types.objectExpression(serializedProperties)];
3440
3534
  if (debug) {
3441
3535
  writeScopeArgs.push(_marko_compiler.types.stringLiteral(path.hub.file.opts.filenameRelative), section.loc && section.loc.start.line != null ? _marko_compiler.types.stringLiteral(`${section.loc.start.line}:${section.loc.start.column + 1}`) : _marko_compiler.types.numericLiteral(0));
3536
+ for (const [accessor, varLoc] of getSectionDebugVars(section)) (debugVars ||= []).push(toObjectProperty(accessor, _marko_compiler.types.valueToNode(varLoc)));
3442
3537
  if (debugVars) writeScopeArgs.push(_marko_compiler.types.objectExpression(debugVars));
3443
3538
  }
3444
3539
  body.push(_marko_compiler.types.expressionStatement(getExprIfSerialized(section, sectionSerializeReason, writeScopeBuilder ? writeScopeBuilder(callRuntime("_scope", ...writeScopeArgs)) : callRuntime("_scope", ...writeScopeArgs))));
@@ -3492,7 +3587,7 @@ function replaceAssignedNode(node) {
3492
3587
  case "UpdateExpression": {
3493
3588
  const { extra } = node.argument;
3494
3589
  if (isAssignedBindingExtra(extra)) {
3495
- let builtAssignment = getBuildAssignment(extra)?.(extra.section, _marko_compiler.types.binaryExpression(node.operator === "++" ? "+" : "-", createScopeReadExpression(extra.assignment, extra.section), _marko_compiler.types.numericLiteral(1)));
3590
+ let builtAssignment = getBuildAssignment(extra)?.(extra.section, _marko_compiler.types.binaryExpression(node.operator === "++" ? "+" : "-", _marko_compiler.types.unaryExpression("+", createScopeReadExpression(extra.assignment, extra.section)), _marko_compiler.types.numericLiteral(1)));
3496
3591
  if (builtAssignment) {
3497
3592
  if (!node.prefix) {
3498
3593
  builtAssignment = _marko_compiler.types.binaryExpression(node.operator === "++" ? "-" : "+", builtAssignment, _marko_compiler.types.numericLiteral(1));
@@ -3576,15 +3671,15 @@ function replaceRegisteredFunctionNode$1(node) {
3576
3671
  switch (node.type) {
3577
3672
  case "ClassMethod": {
3578
3673
  const replacement = getRegisteredFnExpression$1(node);
3579
- return replacement && _marko_compiler.types.classProperty(node.key, replacement);
3674
+ return replacement && _marko_compiler.types.classProperty(node.key, replacement, void 0, void 0, node.computed, node.static);
3580
3675
  }
3581
3676
  case "ClassPrivateMethod": {
3582
3677
  const replacement = getRegisteredFnExpression$1(node);
3583
- return replacement && _marko_compiler.types.classPrivateProperty(node.key, replacement);
3678
+ return replacement && _marko_compiler.types.classPrivateProperty(node.key, replacement, void 0, node.static);
3584
3679
  }
3585
3680
  case "ObjectMethod": {
3586
3681
  const replacement = getRegisteredFnExpression$1(node);
3587
- return replacement && _marko_compiler.types.objectProperty(node.key, replacement);
3682
+ return replacement && _marko_compiler.types.objectProperty(node.key, replacement, node.computed);
3588
3683
  }
3589
3684
  case "ArrowFunctionExpression":
3590
3685
  case "FunctionExpression": return getRegisteredFnExpression$1(node);
@@ -4111,7 +4206,7 @@ function resumeOwnerByMarkerWhenStatic(tagSection, bodySection, nodeBinding, sta
4111
4206
  //#endregion
4112
4207
  //#region src/translator/util/is-event-or-change-handler.ts
4113
4208
  function isEventOrChangeHandler(prop) {
4114
- return /^on[-A-Z][a-zA-Z0-9_$]|[a-zA-Z_$][a-zA-Z0-9_$]*Change$/.test(prop);
4209
+ return /^on[-A-Z]|[a-zA-Z_$][a-zA-Z0-9_$]*Change$/.test(prop);
4115
4210
  }
4116
4211
  //#endregion
4117
4212
  //#region src/translator/util/is-non-html-text.ts
@@ -4176,7 +4271,12 @@ var for_default = {
4176
4271
  if (isAttrTag) return;
4177
4272
  const byAttr = getKnownAttrValues(tag.node).by;
4178
4273
  if (forType !== "of" && byAttr?.type === "StringLiteral") throw tag.hub.buildError(byAttr, `The [\`<for>\` tag](https://markojs.com/docs/reference/core-tag#for) only supports a string \`by\` key with \`of\`; use a \`by=(${forType === "in" ? "key, value" : "index"}) => ...\` function for \`<for ${forType}>\`.`);
4179
- if (byAttr?.type === "Identifier" && !tag.scope.getBinding(byAttr.name) && tag.node.body.params.some((param) => Object.hasOwn(_marko_compiler.types.getBindingIdentifiers(param), byAttr.name))) throw tag.hub.buildError(byAttr, `The \`by=\` attribute is evaluated before the loop runs, so \`${byAttr.name}\` is not in scope. Key with a property name string (\`by="id"\`) or a function (\`by=(${byAttr.name}) => key\`).`);
4274
+ if (byAttr) {
4275
+ const paramNames = /* @__PURE__ */ new Set();
4276
+ for (const param of tag.node.body.params) for (const name in _marko_compiler.types.getBindingIdentifiers(param)) paramNames.add(name);
4277
+ const paramRead = paramNames.size ? findLoopParamRead(byAttr, paramNames) : void 0;
4278
+ if (paramRead) throw tag.hub.buildError(paramRead, `The \`by=\` attribute is evaluated before the loop runs, so \`${paramRead.name}\` is not in scope. Key with a property name string (\`by="id"\`) or a function (\`by=(${paramRead.name}) => key\`).`);
4279
+ }
4180
4280
  const bodySection = startSection(tagBody);
4181
4281
  if (!bodySection) {
4182
4282
  dropNodes(getAllTagReferenceNodes(tag.node));
@@ -4234,7 +4334,7 @@ var for_default = {
4234
4334
  flushInto(tag);
4235
4335
  writeHTMLResumeStatements(tagBody);
4236
4336
  const forTagArgs = getBaseArgsInForTag(forType, forAttrs);
4237
- const forTagHTMLRuntime = branchSerializeReason ? forTypeToHTMLResumeRuntime(forType) : forTypeToRuntime(forType);
4337
+ const forTagHTMLRuntime = branchSerializeReason ? forTypeToBranchRuntime(forType) : forTypeToRuntime(forType);
4238
4338
  forTagArgs.push(_marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.blockStatement(bodyStatements)));
4239
4339
  if (branchSerializeReason) {
4240
4340
  const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
@@ -4280,7 +4380,7 @@ var for_default = {
4280
4380
  const forType = getForType(node);
4281
4381
  const signal = getSignal(tagSection, nodeRef, "for");
4282
4382
  signal.build = () => {
4283
- return callRuntime(forTypeToDOMRuntime(forType), getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(getBranchRendererArgs(bodySection)));
4383
+ return callRuntime(forTypeToBranchRuntime(forType), getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(getBranchRendererArgs(bodySection)));
4284
4384
  };
4285
4385
  const forAttrs = getKnownAttrValues(node);
4286
4386
  const loopArgs = getBaseArgsInForTag(forType, forAttrs);
@@ -4348,6 +4448,27 @@ function getForType(tag) {
4348
4448
  case "until": return attr.name;
4349
4449
  }
4350
4450
  }
4451
+ function findLoopParamRead(node, names) {
4452
+ switch (node.type) {
4453
+ case "Identifier": return names.has(node.name) ? node : void 0;
4454
+ case "MemberExpression":
4455
+ case "OptionalMemberExpression": return findLoopParamRead(node.object, names) || (node.computed ? findLoopParamRead(node.property, names) : void 0);
4456
+ }
4457
+ if (_marko_compiler.types.isFunction(node) || _marko_compiler.types.isClass(node)) return;
4458
+ for (const key of _marko_compiler.types.VISITOR_KEYS[node.type] || []) {
4459
+ if (key === "typeAnnotation" || key === "typeParameters") continue;
4460
+ if (key === "key" && !node.computed) continue;
4461
+ const value = node[key];
4462
+ if (Array.isArray(value)) for (const child of value) {
4463
+ const found = child?.type && findLoopParamRead(child, names);
4464
+ if (found) return found;
4465
+ }
4466
+ else if (value?.type) {
4467
+ const found = findLoopParamRead(value, names);
4468
+ if (found) return found;
4469
+ }
4470
+ }
4471
+ }
4351
4472
  function getLoopKeyBinding(byAttr, paramsBinding, forType) {
4352
4473
  if (!paramsBinding) return;
4353
4474
  if (byAttr) {
@@ -4390,15 +4511,7 @@ function forTypeToRuntime(type) {
4390
4511
  case "until": return "forUntil";
4391
4512
  }
4392
4513
  }
4393
- function forTypeToHTMLResumeRuntime(type) {
4394
- switch (type) {
4395
- case "of": return "_for_of";
4396
- case "in": return "_for_in";
4397
- case "to": return "_for_to";
4398
- case "until": return "_for_until";
4399
- }
4400
- }
4401
- function forTypeToDOMRuntime(type) {
4514
+ function forTypeToBranchRuntime(type) {
4402
4515
  switch (type) {
4403
4516
  case "of": return "_for_of";
4404
4517
  case "in": return "_for_in";
@@ -4667,7 +4780,7 @@ function buildContent(body) {
4667
4780
  }
4668
4781
  if (dynamicSerializeReason) body.node.body.unshift(getScopeReasonDeclaration(bodySection));
4669
4782
  else body.node.body.unshift(_marko_compiler.types.expressionStatement(callRuntime("_scope_reason")));
4670
- return callRuntime(serialized ? "_content_resume" : "_content", _marko_compiler.types.stringLiteral(getResumeRegisterId(bodySection, "content")), _marko_compiler.types.arrowFunctionExpression(body.node.params, _marko_compiler.types.blockStatement(body.node.body)), serialized ? getScopeIdIdentifier(getSection(getAttributeTagParent(body.parentPath))) : void 0);
4783
+ return callRuntime(serialized ? "_content_resume" : "_content", _marko_compiler.types.stringLiteral(getResumeRegisterId(bodySection, "content")), _marko_compiler.types.arrowFunctionExpression(body.node.params, _marko_compiler.types.blockStatement(body.node.body)), getScopeIdIdentifier(getSection(getAttributeTagParent(body.parentPath))));
4671
4784
  } else {
4672
4785
  if (isSectionRendererElided(bodySection)) return;
4673
4786
  return _marko_compiler.types.callExpression(_marko_compiler.types.identifier(bodySection.name), bodySection.referencedLocalClosures ? [scopeIdentifier, _marko_compiler.types.objectExpression(toArray(bodySection.referencedLocalClosures, (ref) => {
@@ -4763,8 +4876,13 @@ var native_tag_default = {
4763
4876
  else if (!_marko_compiler.types.isMarkoText(child)) throw tag.hub.buildError(child, `Only text is allowed inside a \`<${tagName}>\`.`);
4764
4877
  }
4765
4878
  relatedControllable ||= getRelatedControllable(tagName, seen);
4879
+ const valueChangeEval = tagName === "input" && seen.valueChange ? evaluate(seen.valueChange.value) : void 0;
4880
+ if (valueChangeEval && !(valueChangeEval.confident && valueChangeEval.computed == null) && getInputValueMode(seen.type) === "attribute") {
4881
+ const type = evaluate(seen.type.value).computed;
4882
+ throw tag.hub.buildError(seen.valueChange, `\`valueChange\` cannot be used on a \`type="${type}"\` \`<input>\` — user interaction can never change its \`value\`.` + (/^[cr]/i.test(type) ? " Bind `checked` or `checkedValue` instead." : ""));
4883
+ }
4766
4884
  if (relatedControllable && relatedControllable.attrs[1]) hasEventHandlers = true;
4767
- if (node.var || hasDynamicAttributes || hasEventHandlers || textPlaceholders || injectNonce || isDynamicControllable(relatedControllable)) {
4885
+ if (node.var || hasDynamicAttributes || hasEventHandlers || textPlaceholders || injectNonce || seen.content && tagName !== "meta" && !node.body.body.length || isDynamicControllable(relatedControllable)) {
4768
4886
  const tagExtra = node.extra ??= {};
4769
4887
  const tagSection = getOrCreateSection(tag);
4770
4888
  const nodeBinding = tagExtra[kNativeTagBinding] = createBinding("#" + tagName.toLowerCase(), 0, tagSection, void 0, void 0, void 0, void 0, !!node.var);
@@ -4866,6 +4984,20 @@ var native_tag_default = {
4866
4984
  const usedAttrs = getUsedAttrs(tagName, tag.node);
4867
4985
  const { staticAttrs, staticControllable, staticContentAttr, skipExpression, injectNonce } = usedAttrs;
4868
4986
  let { spreadExpression } = usedAttrs;
4987
+ if (!isOptimize() && nodeBinding) {
4988
+ const changeAttr = staticControllable?.attrs[1];
4989
+ if (changeAttr) {
4990
+ const handler = evaluate(changeAttr.value);
4991
+ if (!(handler.confident && handler.computed == null)) setSectionDebugVar(tagSection, getPrefixedScopeAccessor(nodeBinding, getAccessorPrefix().ControlledHandler), changeAttr.name, changeAttr.loc);
4992
+ } else if (spreadExpression) {
4993
+ const spreads = tag.node.attributes.filter((attr) => _marko_compiler.types.isMarkoSpreadAttribute(attr));
4994
+ const spreadLoc = spreads.length === 1 && spreads[0].value.loc;
4995
+ if (spreadLoc && spreadLoc.start.index != null) {
4996
+ const name = "..." + tag.hub.file.code.slice(spreadLoc.start.index, spreadLoc.end.index);
4997
+ for (const prefix of [getAccessorPrefix().ControlledHandler, getAccessorPrefix().EventAttributes]) if (prefix !== getAccessorPrefix().ControlledHandler || getSpreadControllableValueProps(tagName)) setSectionDebugVar(tagSection, getPrefixedScopeAccessor(nodeBinding, prefix), name, spreadLoc);
4998
+ }
4999
+ }
5000
+ }
4869
5001
  if (tagName === "select" && (staticControllable || spreadExpression)) flushBefore(tag);
4870
5002
  write`<${tagName}`;
4871
5003
  if (injectNonce) write`${callRuntime("_attr_nonce")}`;
@@ -4875,6 +5007,7 @@ var native_tag_default = {
4875
5007
  if (hasChangeHandler) addHTMLEffectCall(tagSection, void 0);
4876
5008
  }
4877
5009
  let writeAtStartOfBody;
5010
+ if (tagName === "html" && getMarkoOpts().linkAssets && !tag.node.body.body.some((child) => child.type === "MarkoTag" && child.name.type === "StringLiteral" && child.name.value === "head")) writeAtStartOfBody = callRuntime("_flush_head");
4878
5011
  if (tagName === "select") {
4879
5012
  if (staticControllable) htmlSelectArgs.set(tag.node, {
4880
5013
  value: staticControllable.attrs[0]?.value || buildUndefined$1(),
@@ -5041,7 +5174,7 @@ var native_tag_default = {
5041
5174
  stmt = _marko_compiler.types.expressionStatement(callRuntime(`_attr_${name}_items`, nodeExpr, _marko_compiler.types.objectExpression(props)));
5042
5175
  }
5043
5176
  }
5044
- if (stmt) addStatement("render", tagSection, valueReferences, stmt, !!meta.dynamicItems);
5177
+ if (stmt) addStatement("render", tagSection, valueReferences, stmt, true);
5045
5178
  }
5046
5179
  break;
5047
5180
  }
@@ -5448,7 +5581,7 @@ function trackDelimitedAttrObjectProperties(obj, meta) {
5448
5581
  if (prop.key.type === "Identifier") key = prop.key.name;
5449
5582
  else {
5450
5583
  const keyEval = evaluate(prop.key);
5451
- if (keyEval.confident && typeof keyEval.computed === "string" && !/\s/.test(keyEval.computed)) key = keyEval.computed + "";
5584
+ if (keyEval.confident && typeof keyEval.computed === "string" && !/^$|\s/.test(keyEval.computed)) key = keyEval.computed + "";
5452
5585
  else {
5453
5586
  (dynamicProps ||= []).push(prop);
5454
5587
  continue;
@@ -5562,9 +5695,10 @@ const IfTag = {
5562
5695
  const tagBody = tag.get("body");
5563
5696
  const bodySection = getSectionForBody(tagBody);
5564
5697
  if (bodySection) {
5565
- const [[ifTag]] = getBranches(tag);
5698
+ const branches = getBranches(tag);
5699
+ const [ifTag] = branches[0];
5566
5700
  const ifTagSection = getSection(ifTag);
5567
- resumeOwnerByMarkerWhenStatic(ifTagSection, bodySection, getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection), kStatefulReason$1);
5701
+ resumeOwnerByMarkerWhenStatic(ifTagSection, bodySection, getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length), kStatefulReason$1);
5568
5702
  flushInto(tag);
5569
5703
  writeHTMLResumeStatements(tagBody);
5570
5704
  }
@@ -5572,22 +5706,22 @@ const IfTag = {
5572
5706
  const branches = getBranches(tag);
5573
5707
  const [ifTag] = branches[0];
5574
5708
  const ifTagSection = getSection(ifTag);
5575
- const nodeBinding = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection);
5576
- const onlyChildParentTagName = getOnlyChildParentTagName(ifTag);
5709
+ const nodeBinding = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length);
5710
+ const onlyChildParentTagName = getOnlyChildParentTagName(ifTag, branches.length);
5577
5711
  const markerSerializeReason = getSerializeReason(ifTagSection, nodeBinding);
5578
5712
  const nextTag = tag.getNextSibling();
5579
5713
  let branchSerializeReasons;
5580
5714
  let statement;
5581
5715
  let singleChild = true;
5582
- for (const [, branchBody] of branches) if (!(branchBody?.content?.singleChild && branchBody.content.startType !== 4)) {
5716
+ for (const [, branchBodySection] of branches) if (!(branchBodySection?.content?.singleChild && branchBodySection.content.startType !== 4)) {
5583
5717
  singleChild = false;
5584
5718
  break;
5585
5719
  }
5586
5720
  for (let i = branches.length; i--;) {
5587
- const [branchTag, branchBody] = branches[i];
5721
+ const [branchTag, branchBodySection] = branches[i];
5588
5722
  const bodyStatements = branchTag.node.body.body;
5589
- if (branchBody) {
5590
- const branchSerializeReason = getSerializeReason(branchBody, kBranchSerializeReason);
5723
+ if (branchBodySection) {
5724
+ const branchSerializeReason = getSerializeReason(branchBodySection, kBranchSerializeReason);
5591
5725
  if (branchSerializeReason) {
5592
5726
  if (branchSerializeReasons !== true) if (branchSerializeReason === true || branchSerializeReason.state) branchSerializeReasons = true;
5593
5727
  else if (branchSerializeReasons) branchSerializeReasons = addSorted(compareSources, branchSerializeReasons, branchSerializeReason);
@@ -5626,7 +5760,7 @@ const IfTag = {
5626
5760
  const [ifTag] = branches[0];
5627
5761
  const ifTagSection = getSection(ifTag);
5628
5762
  const ifTagExtra = branches[0][0].node.extra;
5629
- const nodeRef = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection);
5763
+ const nodeRef = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length);
5630
5764
  let expr = _marko_compiler.types.numericLiteral(branches.length);
5631
5765
  for (let i = branches.length; i--;) {
5632
5766
  const [branchTag, branchBodySection] = branches[i];
@@ -5689,7 +5823,7 @@ function flattenTextOnlyConditional(rootTag) {
5689
5823
  const [attr] = node.attributes;
5690
5824
  if (isCoreTagName(tag, "else")) {
5691
5825
  if (node.attributes.length > 1 || attr && (!_marko_compiler.types.isMarkoAttribute(attr) || attr.name !== "if")) return;
5692
- } else if (node.attributes.length !== 1 || !_marko_compiler.types.isMarkoAttribute(attr) || !attr.default) return;
5826
+ } else if (node.attributes.length !== 1 || !_marko_compiler.types.isMarkoAttribute(attr) || !(attr.default || attr.name === "value")) return;
5693
5827
  for (const child of body) if (_marko_compiler.types.isMarkoText(child)) {
5694
5828
  if (_escape(child.value) !== child.value) return;
5695
5829
  } else if (!_marko_compiler.types.isMarkoPlaceholder(child) || !child.escape) return;
@@ -5745,7 +5879,7 @@ function assertHasBody$1(tag) {
5745
5879
  function assertHasValueAttribute$1(tag) {
5746
5880
  const { node } = tag;
5747
5881
  const [valueAttr] = node.attributes;
5748
- if (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default) throw tag.get("name").buildCodeFrameError(`The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) requires a [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
5882
+ if (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !(valueAttr.default || valueAttr.name === "value")) throw tag.get("name").buildCodeFrameError(`The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) requires a [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
5749
5883
  if (node.attributes.length > 1) {
5750
5884
  const start = node.attributes[1].loc?.start;
5751
5885
  const end = node.attributes[node.attributes.length - 1].loc?.end;
@@ -5924,14 +6058,17 @@ function getChangeHandler(tag, attr) {
5924
6058
  if (_marko_compiler.types.isIdentifier(attr.value)) {
5925
6059
  const binding = tag.scope.getBinding(attr.value.name);
5926
6060
  if (!binding) return _marko_compiler.types.markoAttribute(changeAttrName, buildChangeHandlerFunction(attr.value, modifier));
5927
- const existingChangedAttr = BINDING_CHANGE_HANDLER.get(binding.identifier);
6061
+ const modifierKey = modifier?.name ?? "";
6062
+ let handlerByModifier = BINDING_CHANGE_HANDLER.get(binding.identifier);
6063
+ if (!handlerByModifier) BINDING_CHANGE_HANDLER.set(binding.identifier, handlerByModifier = /* @__PURE__ */ new Map());
6064
+ const existingChangedAttr = handlerByModifier.get(modifierKey);
5928
6065
  if (!existingChangedAttr) {
5929
6066
  const bindingIdentifierPath = binding.path.getOuterBindingIdentifierPaths()[binding.identifier.name];
5930
6067
  let changeAttrExpr = bindingIdentifierPath ? bindingIdentifierPath.parentPath === binding.path ? buildChangeHandlerFunction(attr.value, modifier) : bindingIdentifierPath.parentPath.isObjectProperty() ? getChangeHandlerFromObjectPattern(bindingIdentifierPath.parentPath) : void 0 : void 0;
5931
- if (!changeAttrExpr) throw tag.hub.buildError(attr.value, bindingIdentifierPath?.parentPath?.isArrayPattern() ? `Cannot two-way bind to \`${attr.value.name}\` because it comes from array destructuring, which has no change handler. Use object destructuring or pass an explicit \`${changeAttrName}\` attribute.` : "Unable to bind to value.");
6068
+ if (!changeAttrExpr) throw tag.hub.buildError(attr.value, bindingIdentifierPath?.parentPath?.isArrayPattern() ? `Cannot two-way bind to \`${attr.value.name}\` because it comes from array destructuring, which has no change handler. Use object destructuring or pass an explicit \`${changeAttrName}\` attribute.` : bindingIdentifierPath?.parentPath?.isObjectProperty({ computed: true }) ? `Cannot two-way bind to \`${attr.value.name}\` because it is destructured with a dynamically computed key, so its change handler cannot be derived. Use a static key or pass an explicit \`${changeAttrName}\` attribute.` : "Unable to bind to value.");
5932
6069
  if (modifier && _marko_compiler.types.isIdentifier(changeAttrExpr)) changeAttrExpr = _marko_compiler.types.logicalExpression("&&", changeAttrExpr, buildModifierForwarder(_marko_compiler.types.cloneNode(changeAttrExpr), modifier));
5933
6070
  const changeHandlerAttr = _marko_compiler.types.markoAttribute(changeAttrName, changeAttrExpr);
5934
- BINDING_CHANGE_HANDLER.set(binding.identifier, changeHandlerAttr);
6071
+ handlerByModifier.set(modifierKey, changeHandlerAttr);
5935
6072
  return changeHandlerAttr;
5936
6073
  }
5937
6074
  if (existingChangedAttr.type === "Identifier") return _marko_compiler.types.markoAttribute(changeAttrName, withPreviousLocation(_marko_compiler.types.identifier(existingChangedAttr.name), attr.value));
@@ -5939,7 +6076,7 @@ function getChangeHandler(tag, attr) {
5939
6076
  if (!(markoRoot?.isMarkoTag() || markoRoot?.isMarkoTagBody())) throw tag.hub.buildError(attr.value, "Unable to bind to value.");
5940
6077
  const changeHandlerId = generateUid(changeAttrName);
5941
6078
  const changeHandlerConst = _marko_compiler.types.markoTag(_marko_compiler.types.stringLiteral("const"), [_marko_compiler.types.markoAttribute("value", existingChangedAttr.value, null, null, true)], _marko_compiler.types.markoTagBody([]), null, _marko_compiler.types.identifier(changeHandlerId));
5942
- BINDING_CHANGE_HANDLER.set(binding.identifier, existingChangedAttr.value = _marko_compiler.types.identifier(changeHandlerId));
6079
+ handlerByModifier.set(modifierKey, existingChangedAttr.value = _marko_compiler.types.identifier(changeHandlerId));
5943
6080
  if (markoRoot.isMarkoTag()) markoRoot.insertAfter(changeHandlerConst);
5944
6081
  else markoRoot.unshiftContainer("body", changeHandlerConst);
5945
6082
  return _marko_compiler.types.markoAttribute(changeAttrName, withPreviousLocation(_marko_compiler.types.identifier(changeHandlerId), attr.value));
@@ -5969,25 +6106,21 @@ function buildChangeHandlerFunction(id, modifier) {
5969
6106
  function getChangeHandlerFromObjectPattern(parent) {
5970
6107
  let changeKey;
5971
6108
  const pattern = parent.parentPath;
5972
- if (parent.node.computed) {
5973
- changeKey = generateUidIdentifier("dynamicChange");
5974
- pattern.pushContainer("properties", _marko_compiler.types.objectProperty(_marko_compiler.types.binaryExpression("+", parent.get("key").node, _marko_compiler.types.stringLiteral("Change")), changeKey, true));
5975
- } else {
5976
- const searchKey = `${getStringOrIdentifierValue(parent.get("key"))}Change`;
5977
- for (const prop of pattern.get("properties")) if (prop.isObjectProperty()) {
5978
- const propKey = prop.get("key");
5979
- const propValue = prop.get("value");
5980
- if (!prop.node.computed && getStringOrIdentifierValue(propKey) === searchKey && propValue.isIdentifier()) {
5981
- changeKey = propValue.node;
5982
- break;
5983
- }
6109
+ const keyName = getStaticKeyName(parent.node);
6110
+ if (keyName === void 0) return;
6111
+ const searchKey = `${keyName}Change`;
6112
+ for (const prop of pattern.get("properties")) if (prop.isObjectProperty()) {
6113
+ const propValue = prop.get("value");
6114
+ if (getStaticKeyName(prop.node) === searchKey && propValue.isIdentifier()) {
6115
+ changeKey = propValue.node;
6116
+ break;
5984
6117
  }
5985
- if (!changeKey) pattern.unshiftContainer("properties", _marko_compiler.types.objectProperty(_marko_compiler.types.stringLiteral(searchKey), changeKey = generateUidIdentifier(searchKey)));
5986
6118
  }
6119
+ if (!changeKey) pattern.unshiftContainer("properties", _marko_compiler.types.objectProperty(_marko_compiler.types.stringLiteral(searchKey), changeKey = generateUidIdentifier(searchKey)));
5987
6120
  return changeKey;
5988
6121
  }
5989
- function getStringOrIdentifierValue(path) {
5990
- return getLiteralName(path.node);
6122
+ function getStaticKeyName(prop) {
6123
+ return prop.computed && !_marko_compiler.types.isStringLiteral(prop.key) ? void 0 : getLiteralName(prop.key);
5991
6124
  }
5992
6125
  function getLiteralName(node) {
5993
6126
  switch (node.type) {
@@ -6181,7 +6314,7 @@ function crawlSectionsAndSetBinding(tag, binding, properties, skip) {
6181
6314
  }
6182
6315
  //#endregion
6183
6316
  //#region src/translator/util/translate-var.ts
6184
- function translateVar(tag, initialValue, kind = "const") {
6317
+ function translateVar(tag, initialValue, kind = "const", statements) {
6185
6318
  const { node: { var: tagVar } } = tag;
6186
6319
  if (!tagVar) return;
6187
6320
  const tagSection = getOrCreateSection(tag);
@@ -6216,7 +6349,9 @@ function translateVar(tag, initialValue, kind = "const") {
6216
6349
  restPath.remove();
6217
6350
  }
6218
6351
  });
6219
- tag.insertBefore(_marko_compiler.types.variableDeclaration(kind, [_marko_compiler.types.variableDeclarator(tagVar, initialValue)]));
6352
+ const declaration = _marko_compiler.types.variableDeclaration(kind, [_marko_compiler.types.variableDeclarator(tagVar, initialValue)]);
6353
+ if (statements) statements.push(declaration);
6354
+ else tag.insertBefore(declaration);
6220
6355
  }
6221
6356
  function getDestructurePattern(id) {
6222
6357
  let cur = id;
@@ -6252,7 +6387,8 @@ function knownTagAnalyze(tag, contentSection, propTree) {
6252
6387
  const varExpr = tagExtra.defineBodySection ? contentSection.returnValueExpr : mapParamReasonToExpr(exprs, contentSection.returnSerializeReason && (contentSection.returnSerializeReason === true || !!contentSection.returnSerializeReason.state || contentSection.returnSerializeReason.param));
6253
6388
  varBinding.scopeOffset = tagExtra[kChildOffsetScopeBinding$1] = createBinding("#scopeOffset", 0, section);
6254
6389
  setBindingDownstream(varBinding, varExpr);
6255
- addSerializeExpr(section, mutatesTagVar || varExpr, childScopeBinding);
6390
+ if (mutatesTagVar) addSerializeExpr(section, true, childScopeBinding);
6391
+ addSerializeExpr(section, varExpr, childScopeBinding);
6256
6392
  }
6257
6393
  addSerializeExpr(section, fromIter(attrExprs), childScopeBinding);
6258
6394
  }
@@ -6270,13 +6406,13 @@ function knownTagTranslateHTML(tag, tagIdentifier, contentSection, propTree) {
6270
6406
  statements: []
6271
6407
  };
6272
6408
  const childScopeBinding = tagExtra[kChildScopeBinding];
6273
- if (getSerializeReason(section, childScopeBinding)) {
6409
+ const childScopeSerializeReason = getSerializeReason(section, childScopeBinding);
6410
+ let varStatement;
6411
+ if (childScopeSerializeReason) {
6274
6412
  const peekScopeId = generateUidIdentifier(childScopeBinding?.name);
6275
- const peekScopeDeclaration = _marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(peekScopeId, callRuntime("_peek_scope_id"))]);
6276
- if (tagVar) tag.insertBefore(peekScopeDeclaration);
6277
- else statements.push(peekScopeDeclaration);
6413
+ statements.push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(peekScopeId, callRuntime("_peek_scope_id"))]));
6278
6414
  setBindingSerializedValue(section, childScopeBinding, callRuntime("_existing_scope", peekScopeId));
6279
- if (tagVar) statements.push(_marko_compiler.types.expressionStatement(callRuntime("_var", getScopeIdIdentifier(section), getScopeAccessorLiteral(tag.node.extra[kChildOffsetScopeBinding$1]), peekScopeId, _marko_compiler.types.stringLiteral(getResumeRegisterId(section, tagVar.extra?.binding, "var")))));
6415
+ if (tagVar) varStatement = _marko_compiler.types.expressionStatement(callRuntime("_var", getScopeIdIdentifier(section), getScopeAccessorLiteral(tag.node.extra[kChildOffsetScopeBinding$1]), peekScopeId, _marko_compiler.types.stringLiteral(getResumeRegisterId(section, tagVar.extra?.binding, "var"))));
6280
6416
  }
6281
6417
  if (contentSection.paramReasonGroups) {
6282
6418
  let childSerializeReasonExpr;
@@ -6314,8 +6450,10 @@ function knownTagTranslateHTML(tag, tagIdentifier, contentSection, propTree) {
6314
6450
  if (!tag.node.arguments?.length || properties.length) renderArgs.push(propsToExpression(properties));
6315
6451
  return renderArgs;
6316
6452
  };
6317
- if (tagVar) translateVar(tag, callExpression(tagIdentifier, ...getArgs()), "let");
6318
- else statements.push(callStatement(tagIdentifier, ...getArgs()));
6453
+ if (tagVar) {
6454
+ translateVar(tag, callExpression(tagIdentifier, ...getArgs()), "let", statements);
6455
+ if (varStatement) statements.push(varStatement);
6456
+ } else statements.push(callStatement(tagIdentifier, ...getArgs()));
6319
6457
  for (const replacement of tag.replaceWithMultiple(statements)) replacement.skip();
6320
6458
  }
6321
6459
  function knownTagTranslateDOM(tag, propTree, getBindingIdentifier, callSetup) {
@@ -6325,7 +6463,8 @@ function knownTagTranslateDOM(tag, propTree, getBindingIdentifier, callSetup) {
6325
6463
  if (node.var) {
6326
6464
  const varBinding = node.var.extra.binding;
6327
6465
  const source = initValue(varBinding);
6328
- source.register = !!getSerializeReason(tagSection, childScopeBinding) || !signalHasStatements(source);
6466
+ source.register = !!getSerializeReason(tagSection, childScopeBinding);
6467
+ source.referenced = true;
6329
6468
  source.buildAssignment = (valueSection, value) => {
6330
6469
  const changeArgs = [createScopeReadExpression(childScopeBinding, valueSection), value];
6331
6470
  if (!isOptimize()) changeArgs.push(_marko_compiler.types.stringLiteral(varBinding.name));
@@ -6572,36 +6711,31 @@ function applyAttrObject(tag, propTree, tagInputIdentifier, info) {
6572
6711
  let translatedProps = propsToExpression(translatedAttrs.properties);
6573
6712
  if (translatedAttrs.statements.length) addStatement("render", info.tagSection, referencedBindings, translatedAttrs.statements);
6574
6713
  if ((0, _marko_compiler_babel_utils.isAttributeTag)(tag)) {
6575
- translatedProps = _marko_compiler.types.objectExpression(translatedAttrs.properties);
6576
- const attrTagName = getTagName(tag);
6577
- const parentTag = tag.parentPath;
6578
- if (analyzeAttributeTags(parentTag)?.[attrTagName]?.repeated) {
6579
- let attrTagCallsForTag = (info.attrTagCallsByTag ||= /* @__PURE__ */ new Map()).get(parentTag);
6580
- if (!attrTagCallsForTag) info.attrTagCallsByTag.set(parentTag, attrTagCallsForTag = /* @__PURE__ */ new Map());
6581
- const attrTagCall = attrTagCallsForTag.get(attrTagName);
6582
- if (attrTagCall) {
6583
- attrTagCall.expression = callRuntime("attrTags", attrTagCall.expression, translatedProps);
6584
- return;
6585
- } else attrTagCallsForTag.set(attrTagName, translatedProps = _marko_compiler.types.parenthesizedExpression(callRuntime("attrTag", translatedProps)));
6586
- } else translatedProps = callRuntime("attrTag", translatedProps);
6714
+ const repeated = analyzeAttributeTags(tag.parentPath)?.[getTagName(tag)]?.repeated;
6715
+ const mergedProps = getAttrTagProps(tag, repeated, _marko_compiler.types.objectExpression(translatedAttrs.properties), info);
6716
+ if (!mergedProps) return;
6717
+ translatedProps = mergedProps;
6587
6718
  }
6588
6719
  addStatement("render", info.tagSection, referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(tagInputIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), translatedProps])), true);
6589
6720
  }
6590
6721
  function translateAttrTag(tag, attrTagMeta, info, statements) {
6591
6722
  const translatedAttrs = translateAttrs(tag, true, void 0, statements);
6592
- let translatedProps = _marko_compiler.types.objectExpression(translatedAttrs.properties);
6723
+ return getAttrTagProps(tag, attrTagMeta.repeated, _marko_compiler.types.objectExpression(translatedAttrs.properties), info);
6724
+ }
6725
+ function getAttrTagProps(tag, repeated, translatedProps, info) {
6726
+ if (!repeated) return callRuntime("attrTag", translatedProps);
6593
6727
  const attrTagName = getTagName(tag);
6594
6728
  const parentTag = tag.parentPath;
6595
- if (attrTagMeta.repeated) {
6596
- let attrTagCallsForTag = (info.attrTagCallsByTag ||= /* @__PURE__ */ new Map()).get(parentTag);
6597
- if (!attrTagCallsForTag) info.attrTagCallsByTag.set(parentTag, attrTagCallsForTag = /* @__PURE__ */ new Map());
6598
- const attrTagCall = attrTagCallsForTag.get(attrTagName);
6599
- if (attrTagCall) {
6600
- attrTagCall.expression = callRuntime("attrTags", attrTagCall.expression, translatedProps);
6601
- return;
6602
- } else attrTagCallsForTag.set(attrTagName, translatedProps = _marko_compiler.types.parenthesizedExpression(callRuntime("attrTag", translatedProps)));
6603
- } else translatedProps = callRuntime("attrTag", translatedProps);
6604
- return translatedProps;
6729
+ let attrTagCallsForTag = (info.attrTagCallsByTag ||= /* @__PURE__ */ new Map()).get(parentTag);
6730
+ if (!attrTagCallsForTag) info.attrTagCallsByTag.set(parentTag, attrTagCallsForTag = /* @__PURE__ */ new Map());
6731
+ const attrTagCall = attrTagCallsForTag.get(attrTagName);
6732
+ if (attrTagCall) {
6733
+ attrTagCall.expression = callRuntime("attrTags", attrTagCall.expression, translatedProps);
6734
+ return;
6735
+ }
6736
+ const wrappedProps = _marko_compiler.types.parenthesizedExpression(callRuntime("attrTag", translatedProps));
6737
+ attrTagCallsForTag.set(attrTagName, wrappedProps);
6738
+ return wrappedProps;
6605
6739
  }
6606
6740
  function writeAttrsToSignals(tag, propTree, importAlias, info) {
6607
6741
  if (!propTree.props) {
@@ -6776,11 +6910,11 @@ function mapParamReasonToExpr(exprs, reason) {
6776
6910
  }
6777
6911
  }
6778
6912
  function mapParamBindingToExpr(exprs, binding) {
6779
- const isRest = binding.property === void 0 && binding.excludeProperties !== void 0;
6913
+ const isWholeAlias = binding.property === void 0 && binding.upstreamAlias !== void 0;
6780
6914
  const props = [];
6781
- let curBinding = isRest ? binding.upstreamAlias : binding;
6782
- while (curBinding && curBinding.property !== void 0) {
6783
- props.push(curBinding.property);
6915
+ let curBinding = isWholeAlias ? binding.upstreamAlias : binding;
6916
+ while (curBinding && (curBinding.property !== void 0 || curBinding.upstreamAlias)) {
6917
+ if (curBinding.property !== void 0) props.push(curBinding.property);
6784
6918
  curBinding = curBinding.upstreamAlias;
6785
6919
  }
6786
6920
  let curExpr = exprs;
@@ -6789,7 +6923,7 @@ function mapParamBindingToExpr(exprs, binding) {
6789
6923
  if (!nestedExpr) return curExpr.value;
6790
6924
  curExpr = nestedExpr;
6791
6925
  }
6792
- if (isRest) {
6926
+ if (isWholeAlias) {
6793
6927
  let result = curExpr.value;
6794
6928
  if (curExpr.known) {
6795
6929
  for (const key in curExpr.known) if (!includes(binding.excludeProperties, key)) result = concat(result, curExpr.known[key].value);
@@ -6818,6 +6952,11 @@ function getRootSection(section) {
6818
6952
  //#endregion
6819
6953
  //#region src/translator/util/references.ts
6820
6954
  const kBranchSerializeReason = Symbol("branch serialize reason");
6955
+ const globalSources = {
6956
+ state: void 0,
6957
+ param: void 0,
6958
+ global: true
6959
+ };
6821
6960
  const [getBindings] = createProgramState(() => /* @__PURE__ */ new Set());
6822
6961
  const [getNextBindingId, setNextBindingId] = createProgramState(() => 0);
6823
6962
  function createBinding(name, type, refSection, upstreamAlias, property, excludeProperties, loc = null, refDeclared = false) {
@@ -6879,7 +7018,7 @@ function trackDomVarReferences(tag, binding) {
6879
7018
  const babelBinding = tag.scope.getBinding(tagVar.name);
6880
7019
  const section = getOrCreateSection(tag);
6881
7020
  binding.originalName = tagVar.name;
6882
- if (babelBinding.constantViolations.length) for (const ref of babelBinding.constantViolations) throw ref.type === "MarkoTag" ? ref.get("var").buildCodeFrameError(`Duplicate declaration ${JSON.stringify(binding.originalName)}`) : ref.buildCodeFrameError("Tag variables on native elements cannot be assigned to.");
7021
+ if (babelBinding.constantViolations.length) for (const ref of babelBinding.constantViolations) throw ref.type === "MarkoTag" ? ref.get("var").buildCodeFrameError(`Duplicate declaration of \`${binding.originalName}\`.`) : ref.buildCodeFrameError(`\`${binding.originalName}\` is a [tag variable](https://markojs.com/docs/reference/language#tag-variables) on a native element (an element reference) and cannot be assigned to.`);
6883
7022
  for (const ref of babelBinding.referencePaths) {
6884
7023
  const refSection = getOrCreateSection(ref);
6885
7024
  const invoked = isInvokedFunction(ref);
@@ -6902,9 +7041,9 @@ function trackVarReferences(tag, type, upstreamAlias) {
6902
7041
  const section = getOrCreateSection(tag);
6903
7042
  let canonicalUpstreamAlias = upstreamAlias && getCanonicalBinding(upstreamAlias);
6904
7043
  if (canonicalUpstreamAlias) {
6905
- const { excludeProperties } = canonicalUpstreamAlias;
7044
+ const { excludeProperties, restOffset } = canonicalUpstreamAlias;
6906
7045
  if (excludeProperties !== void 0) canonicalUpstreamAlias = canonicalUpstreamAlias.upstreamAlias;
6907
- createBindingsAndTrackReferences(tagVar, canonicalUpstreamAlias.type, tag.scope, section, canonicalUpstreamAlias, void 0, excludeProperties);
7046
+ createBindingsAndTrackReferences(tagVar, canonicalUpstreamAlias.type, tag.scope, section, canonicalUpstreamAlias, void 0, excludeProperties, restOffset);
6908
7047
  return canonicalUpstreamAlias;
6909
7048
  }
6910
7049
  createBindingsAndTrackReferences(tagVar, type, tag.scope, section, void 0, void 0, void 0);
@@ -6957,7 +7096,7 @@ function trackReferencesForBinding(babelBinding, binding) {
6957
7096
  for (const ref of referencePaths) {
6958
7097
  const refSection = getOrCreateSection(ref);
6959
7098
  const markoRoot = getMarkoRoot(ref);
6960
- if (markoRoot?.type === "MarkoAttribute" && markoRoot.parentPath === babelBinding.path) throw ref.buildCodeFrameError(`Tag variable circular references are not supported.`);
7099
+ if (markoRoot?.type === "MarkoAttribute" && markoRoot.parentPath === babelBinding.path) throw ref.buildCodeFrameError(`\`${ref.node.name}\` is the [tag variable](https://markojs.com/docs/reference/language#tag-variables) this tag declares, so its own attributes cannot read it.`);
6961
7100
  else if (isReferenceHoisted(babelBinding.path, ref)) {
6962
7101
  const invoked = isInvokedFunction(ref);
6963
7102
  if (invoked) setReferencesScope(ref);
@@ -6979,8 +7118,8 @@ function trackReferencesForBinding(babelBinding, binding) {
6979
7118
  }
6980
7119
  }
6981
7120
  for (const ref of constantViolations) {
6982
- if (ref.type === "MarkoTag") throw ref.get("var").buildCodeFrameError(`Duplicate declaration ${JSON.stringify(binding.name)}`);
6983
- if (isReferenceHoisted(babelBinding.path, ref)) throw ref.buildCodeFrameError("Cannot assign to hoisted tag variable.");
7121
+ if (ref.type === "MarkoTag") throw ref.get("var").buildCodeFrameError(`Duplicate declaration of \`${binding.name}\`.`);
7122
+ if (isReferenceHoisted(babelBinding.path, ref)) throw ref.buildCodeFrameError(`\`${binding.name}\` is declared by a tag below this assignment; a [tag variable](https://markojs.com/docs/reference/language#tag-variables) can only be assigned below its declaration. Move the declaring tag above this code.`);
6984
7123
  if (ref.isUpdateExpression()) trackAssignment(ref.get("argument"), binding);
6985
7124
  else if (ref.isAssignmentExpression()) {
6986
7125
  trackAssignment(ref.get("left"), binding);
@@ -6988,12 +7127,13 @@ function trackReferencesForBinding(babelBinding, binding) {
6988
7127
  const left = ref.get("left");
6989
7128
  if (left.isIdentifier()) trackReference(left, binding);
6990
7129
  }
6991
- }
7130
+ } else if (ref.isForXStatement()) throw ref.get("left").buildCodeFrameError(`\`${binding.name}\` is a [tag variable](https://markojs.com/docs/reference/language#tag-variables), so a \`for...${ref.isForOfStatement() ? "of" : "in"}\` cannot assign to it. Loop into a local variable and assign \`${binding.name}\` from it instead.`);
6992
7131
  }
6993
7132
  }
6994
7133
  function trackAssignment(assignment, binding) {
6995
7134
  const fnParent = getFnParent(assignment);
6996
- if (!fnParent) throw assignment.buildCodeFrameError(`Assignments to a tag ${binding.type === 3 ? "parameter" : "variable"} must be within a script or function.`);
7135
+ if (!fnParent) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag ${binding.type === 3 ? "parameter" : "variable"} and can only be assigned within a script or function.`);
7136
+ if (binding.type === 4) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag parameter and cannot be assigned to.`);
6997
7137
  const fnRoot = getFnRoot(fnParent);
6998
7138
  const fnExtra = fnRoot && (fnRoot.node.extra ??= {});
6999
7139
  const section = getOrCreateSection(assignment);
@@ -7022,6 +7162,10 @@ function setReferencesScope(path) {
7022
7162
  const fnRoot = getFnRoot(path);
7023
7163
  if (fnRoot) (fnRoot.node.extra ??= {}).referencesScope = true;
7024
7164
  }
7165
+ const [getGlobalBinding] = createProgramState(() => createBinding("$global", 7, getOrCreateSection((0, _marko_compiler_babel_utils.getProgram)())));
7166
+ function trackGlobalReference(path) {
7167
+ trackReference(path, getGlobalBinding());
7168
+ }
7025
7169
  function createBindingsAndTrackReferences(lVal, type, scope, section, upstreamAlias, property, excludeProperties, restOffset) {
7026
7170
  switch (lVal.type) {
7027
7171
  case "Identifier": {
@@ -7049,14 +7193,14 @@ function createBindingsAndTrackReferences(lVal, type, scope, section, upstreamAl
7049
7193
  }
7050
7194
  case "ArrayPattern": {
7051
7195
  const patternBinding = (property ? upstreamAlias.propertyAliases.get(property) : upstreamAlias) || ((lVal.extra ??= {}).binding = createBinding(generateUid(property || "pattern"), type, section, upstreamAlias, property, excludeProperties, lVal.loc));
7052
- let i = -1;
7196
+ let index = (restOffset || 0) - 1;
7053
7197
  for (const element of lVal.elements) {
7054
- i++;
7198
+ index++;
7055
7199
  if (element) {
7056
7200
  if (element.type === "RestElement") {
7057
- excludeProperties = i > 0 ? addNumericPropertiesUntil(excludeProperties, i) : void 0;
7058
- createBindingsAndTrackReferences(element.argument, type, scope, section, patternBinding, void 0, excludeProperties, i);
7059
- } else if (_marko_compiler.types.isLVal(element)) createBindingsAndTrackReferences(element, type, scope, section, patternBinding, `${i}`, void 0);
7201
+ excludeProperties = index > 0 ? addNumericPropertiesUntil(excludeProperties, index) : void 0;
7202
+ createBindingsAndTrackReferences(element.argument, type, scope, section, patternBinding, void 0, excludeProperties, index);
7203
+ } else if (_marko_compiler.types.isLVal(element)) createBindingsAndTrackReferences(element, type, scope, section, patternBinding, `${index}`, void 0);
7060
7204
  }
7061
7205
  }
7062
7206
  break;
@@ -7144,6 +7288,7 @@ function finalizeReferences() {
7144
7288
  const exprBindings = resolveReferencedBindings(expr, reads, intersectionsBySection);
7145
7289
  expr.referencedBindings = exprBindings.referencedBindings;
7146
7290
  expr.lazyBindings = exprBindings.lazyBindings;
7291
+ expr.globalBindings = exprBindings.globalBindings;
7147
7292
  if (!exprBindings.referencedBindings) addSetupStatement(expr.section);
7148
7293
  forEach(exprBindings.lazyBindings, (binding) => {
7149
7294
  binding.forcePersist = true;
@@ -7159,7 +7304,9 @@ function finalizeReferences() {
7159
7304
  forEach(exprBindings.lazyBindings, (binding) => {
7160
7305
  addSerializeReason(binding.section, true, binding);
7161
7306
  });
7162
- }
7307
+ } else forEach(reads, (read) => {
7308
+ if (read.serializedValue) addSerializeExpr(read.binding.section, expr, read.binding);
7309
+ });
7163
7310
  if (exprBindings.allBindings) {
7164
7311
  const exprFnReads = fnReadsByExpression.get(expr);
7165
7312
  if (exprFnReads) for (const [fn, fnReads] of exprFnReads) {
@@ -7189,6 +7336,10 @@ function finalizeReferences() {
7189
7336
  forEachSection(finalizeTagDownstreams);
7190
7337
  for (const binding of bindings) {
7191
7338
  const { name, section } = binding;
7339
+ if (binding.type === 7) {
7340
+ resolveBindingSources(binding);
7341
+ continue;
7342
+ }
7192
7343
  if (binding.type !== 0) {
7193
7344
  resolveBindingSources(binding);
7194
7345
  forEach(binding.assignmentSections, (assignedSection) => {
@@ -7223,7 +7374,8 @@ function finalizeReferences() {
7223
7374
  section.referencedClosures = bindingUtil.add(section.referencedClosures, canonicalUpstreamAlias);
7224
7375
  }
7225
7376
  setReadsOwner(section, canonicalUpstreamAlias.section);
7226
- addOwnerSerializeReason(section, canonicalUpstreamAlias.section, !!isEffect || canonicalUpstreamAlias.sources);
7377
+ if (isEffect) addOwnerSerializeReason(section, canonicalUpstreamAlias.section, true);
7378
+ addOwnerSerializeReason(section, canonicalUpstreamAlias.section, canonicalUpstreamAlias.sources);
7227
7379
  }
7228
7380
  }
7229
7381
  }
@@ -7235,7 +7387,8 @@ function finalizeReferences() {
7235
7387
  addOwnerSerializeReason(section, hoistedBinding.section, true);
7236
7388
  });
7237
7389
  if (section.parent && section.isBranch && section.sectionAccessor && section.upstreamExpression) {
7238
- addSerializeReason(section, !!(section.isHoistThrough || section.hoisted) || getSerializeSourcesForRef(getDirectClosures(section)), kBranchSerializeReason);
7390
+ if (section.isHoistThrough || section.hoisted) addSerializeReason(section, true, kBranchSerializeReason);
7391
+ addSerializeReason(section, getSerializeSourcesForRef(getDirectClosures(section)), kBranchSerializeReason);
7239
7392
  addSerializeExpr(section, section.upstreamExpression, kBranchSerializeReason);
7240
7393
  addSerializeExpr(section.parent, section.upstreamExpression, section.sectionAccessor.binding);
7241
7394
  }
@@ -7266,16 +7419,16 @@ function finalizeReferences() {
7266
7419
  forEach(section.referencedClosures, (closure) => {
7267
7420
  const sourceSection = closure.section;
7268
7421
  let currentSection = section;
7269
- let branchesReason;
7422
+ let branchesForced = false;
7423
+ let branchesSources;
7270
7424
  while (currentSection !== sourceSection) {
7271
7425
  const upstreamReason = currentSection.downstreamBinding ? getSectionRegisterReasons(currentSection) || void 0 : !currentSection.upstreamExpression || getSerializeSourcesForExpr(currentSection.upstreamExpression);
7272
- if (upstreamReason === true) {
7273
- branchesReason = true;
7274
- break;
7275
- }
7276
- branchesReason = mergeSerializeReasons(branchesReason, upstreamReason);
7426
+ if (upstreamReason === true) branchesForced = true;
7427
+ else if (upstreamReason) branchesSources = mergeSources(branchesSources, upstreamReason);
7277
7428
  currentSection = currentSection.parent;
7278
7429
  }
7430
+ const branchesReason = branchesForced || branchesSources;
7431
+ if (branchesForced) addSerializeReason(sourceSection, branchesSources, closure);
7279
7432
  addSerializeReason(sourceSection, branchesReason, closure);
7280
7433
  addSerializeReason(sourceSection, getSerializeReason(sourceSection, closure));
7281
7434
  if (isDynamicClosure(section, closure)) {
@@ -7426,6 +7579,9 @@ function resolveBindingSources(binding) {
7426
7579
  case 3:
7427
7580
  binding.sources = createSources(void 0, getCanonicalBinding(binding));
7428
7581
  return;
7582
+ case 7:
7583
+ binding.sources = globalSources;
7584
+ return;
7429
7585
  }
7430
7586
  const aliasRoot = getAliasRoot(binding);
7431
7587
  if (aliasRoot) {
@@ -7462,15 +7618,17 @@ function resolveDerivedSources(binding) {
7462
7618
  });
7463
7619
  }
7464
7620
  }
7465
- function createSources(state, param) {
7466
- if (!(state || param)) throw new Error("Cannot create a serialize reason that does not reference state or a param.");
7621
+ function createSources(state, param, global) {
7622
+ if (!(state || param || global)) throw new Error("Cannot create a serialize reason that does not reference state, a param, or $global.");
7467
7623
  return {
7468
7624
  state,
7469
- param
7625
+ param,
7626
+ global
7470
7627
  };
7471
7628
  }
7472
7629
  function compareSources(a, b) {
7473
7630
  let delta;
7631
+ if (a.global !== b.global) return a.global ? 1 : -1;
7474
7632
  if (a.param) {
7475
7633
  if (!b.param) return 1;
7476
7634
  if (delta = compareReferences(a.param, b.param)) return delta;
@@ -7484,8 +7642,8 @@ function compareSources(a, b) {
7484
7642
  function mergeSources(a, b) {
7485
7643
  if (!a) return b;
7486
7644
  if (!b) return a;
7487
- if (a.state === b.state && a.param === b.param) return a;
7488
- return createSources(bindingUtil.union(a.state, b.state), unionParamSources(a.param, b.param));
7645
+ if (a.state === b.state && a.param === b.param && a.global === b.global) return a;
7646
+ return createSources(bindingUtil.union(a.state, b.state), unionParamSources(a.param, b.param), a.global || b.global);
7489
7647
  }
7490
7648
  function unionParamSources(a, b) {
7491
7649
  const merged = bindingUtil.union(a, b);
@@ -7545,6 +7703,14 @@ function dropExtra(exprExtra) {
7545
7703
  });
7546
7704
  }
7547
7705
  }
7706
+ function isSerializedChangeHandlerRead(exprRoot) {
7707
+ const markoRoot = getMarkoRoot(exprRoot);
7708
+ if (!markoRoot?.isMarkoAttribute()) return false;
7709
+ const attr = markoRoot.node;
7710
+ if (!isEventOrChangeHandler(attr.name) || isEventHandler(attr.name) || _marko_compiler.types.isFunction(attr.value)) return false;
7711
+ const tag = markoRoot.parentPath;
7712
+ return tag.isMarkoTag() && (tag.node.name.type !== "StringLiteral" || (0, _marko_compiler_babel_utils.isNativeTag)(tag));
7713
+ }
7548
7714
  function addReadToExpression(root, binding, getter) {
7549
7715
  const { node } = root;
7550
7716
  const fnRoot = getFnRoot(root);
@@ -7552,6 +7718,7 @@ function addReadToExpression(root, binding, getter) {
7552
7718
  const section = getOrCreateSection(exprRoot);
7553
7719
  const exprExtra = getCanonicalExtra(exprRoot.node.extra ??= { section });
7554
7720
  const read = addRead(exprExtra, node.extra ??= {}, binding, section, getter);
7721
+ if (!fnRoot && isSerializedChangeHandlerRead(exprRoot)) read.serializedValue = true;
7555
7722
  const { parent } = root;
7556
7723
  if (parent.type === "BinaryExpression" && (parent.operator === "===" || parent.operator === "!==")) read.comparedTo = parent.left === node ? parent.right : parent.left;
7557
7724
  if (!getter && binding.type === 5) {
@@ -7758,13 +7925,13 @@ function resolveReferencedBindingsInFunction(refs, reads) {
7758
7925
  const { getter, binding } = read;
7759
7926
  if (getter) {} else if (binding.type === 6) {
7760
7927
  if (bindingUtil.find(refs, binding)) constantBindings = bindingUtil.add(constantBindings, binding);
7761
- } else if (binding.type !== 0) referencedBindings = bindingUtil.add(referencedBindings, findClosestReference(read.binding, refs));
7928
+ } else if (binding.type !== 0 && binding.type !== 7) referencedBindings = bindingUtil.add(referencedBindings, findClosestReference(read.binding, refs));
7762
7929
  }
7763
7930
  else {
7764
7931
  const { getter, binding } = reads;
7765
7932
  if (getter) {} else if (binding.type === 6) {
7766
7933
  if (bindingUtil.find(refs, binding)) constantBindings = binding;
7767
- } else if (binding.type !== 0) referencedBindings = findClosestReference(binding, refs);
7934
+ } else if (binding.type !== 0 && binding.type !== 7) referencedBindings = findClosestReference(binding, refs);
7768
7935
  }
7769
7936
  return {
7770
7937
  referencedBindings,
@@ -7823,6 +7990,7 @@ function resolveReferencedBindings(expr, reads, intersectionsBySection) {
7823
7990
  let hoistedBindings;
7824
7991
  let allBindings;
7825
7992
  let lazyBindings;
7993
+ let globalBindings;
7826
7994
  if (Array.isArray(reads)) {
7827
7995
  const rootBindings = getRootBindings(reads);
7828
7996
  for (const read of reads) {
@@ -7841,11 +8009,12 @@ function resolveReferencedBindings(expr, reads, intersectionsBySection) {
7841
8009
  if (isChangeHandlerRead) {
7842
8010
  const upstreamRoot = binding.upstreamAlias && findClosestReference(binding.upstreamAlias, rootBindings);
7843
8011
  if (upstreamRoot) binding = upstreamRoot;
7844
- } else {
8012
+ } else if (binding.type !== 7) {
7845
8013
  extra.section = expr.section;
7846
8014
  ({binding} = extra.read ??= resolveExpressionReference(rootBindings, binding));
7847
8015
  }
7848
- if (isLazyRead(expr, read, binding, isChangeHandlerRead)) lazyBindings = bindingUtil.add(lazyBindings, binding);
8016
+ if (binding.type === 7) globalBindings = bindingUtil.add(globalBindings, binding);
8017
+ else if (isLazyRead(expr, read, binding, isChangeHandlerRead)) lazyBindings = bindingUtil.add(lazyBindings, binding);
7849
8018
  else if (binding.type === 6) constantBindings = bindingUtil.add(constantBindings, binding);
7850
8019
  else if (binding.type !== 0) referencedBindings = bindingUtil.add(referencedBindings, binding);
7851
8020
  }
@@ -7860,7 +8029,8 @@ function resolveReferencedBindings(expr, reads, intersectionsBySection) {
7860
8029
  binding.hoists = sectionUtil.add(binding.hoists, getter.hoisted);
7861
8030
  hoistedBindings = bindingUtil.add(hoistedBindings, binding);
7862
8031
  }
7863
- } else {
8032
+ } else if (binding.type === 7) globalBindings = binding;
8033
+ else {
7864
8034
  extra.read = createRead(binding, void 0, ownVar);
7865
8035
  if (isLazyRead(expr, reads, binding, extra.assignmentTo === binding)) lazyBindings = binding;
7866
8036
  else if (binding.type === 6) constantBindings = binding;
@@ -7892,7 +8062,8 @@ function resolveReferencedBindings(expr, reads, intersectionsBySection) {
7892
8062
  constantBindings,
7893
8063
  hoistedBindings,
7894
8064
  allBindings,
7895
- lazyBindings
8065
+ lazyBindings,
8066
+ globalBindings
7896
8067
  };
7897
8068
  }
7898
8069
  function resolveExpressionReference(rootBindings, readBinding) {
@@ -8132,27 +8303,34 @@ var class_default = {
8132
8303
  }
8133
8304
  };
8134
8305
  //#endregion
8306
+ //#region src/translator/util/statement-tag.ts
8307
+ function createStatementTag(keyword) {
8308
+ const target = keyword === "static" ? void 0 : keyword;
8309
+ const keywordReg = new RegExp(`^${keyword}\\s*`);
8310
+ return {
8311
+ parse(tag) {
8312
+ const { node, hub: { file } } = tag;
8313
+ const rawValue = node.rawValue;
8314
+ const code = rawValue.replace(keywordReg, "");
8315
+ const start = node.start + (rawValue.length - code.length);
8316
+ let body = (0, _marko_compiler_babel_utils.parseStatements)(file, code, start, start + code.length);
8317
+ if (body.length === 1 && _marko_compiler.types.isBlockStatement(body[0])) body = body[0].body;
8318
+ tag.replaceWith(_marko_compiler.types.markoScriptlet(body, true, target));
8319
+ },
8320
+ parseOptions: {
8321
+ statement: true,
8322
+ rawOpenTag: true
8323
+ },
8324
+ autocomplete: [{
8325
+ displayText: `${keyword} <statement>`,
8326
+ description: `A JavaScript statement which is only evaluated once your template is loaded${target ? ` on the ${target}` : ""}.`,
8327
+ descriptionMoreURL: `https://markojs.com/docs/reference/language#${keyword === "static" ? "static" : "server-and-client"}`
8328
+ }]
8329
+ };
8330
+ }
8331
+ //#endregion
8135
8332
  //#region src/translator/core/client.ts
8136
- var client_default = {
8137
- parse(tag) {
8138
- const { node, hub: { file } } = tag;
8139
- const rawValue = node.rawValue;
8140
- const code = rawValue.replace(/^client\s*/, "");
8141
- const start = node.start + (rawValue.length - code.length);
8142
- let body = (0, _marko_compiler_babel_utils.parseStatements)(file, code, start, start + code.length);
8143
- if (body.length === 1 && _marko_compiler.types.isBlockStatement(body[0])) body = body[0].body;
8144
- tag.replaceWith(_marko_compiler.types.markoScriptlet(body, true, "client"));
8145
- },
8146
- parseOptions: {
8147
- statement: true,
8148
- rawOpenTag: true
8149
- },
8150
- autocomplete: [{
8151
- displayText: "client <statement>",
8152
- description: "A JavaScript statement which is only evaluated once your template is loaded on the client.",
8153
- descriptionMoreURL: "https://markojs.com/docs/syntax/#client-javascript"
8154
- }]
8155
- };
8333
+ var client_default = createStatementTag("client");
8156
8334
  //#endregion
8157
8335
  //#region src/translator/core/const.ts
8158
8336
  var const_default = {
@@ -8289,8 +8467,8 @@ var define_default = {
8289
8467
  if (isOutputHTML()) {
8290
8468
  flushInto(tag);
8291
8469
  writeHTMLResumeStatements(tag.get("body"));
8470
+ translateVar(tag, propsToExpression(translatedAttrs.properties), "const", translatedAttrs.statements);
8292
8471
  tag.insertBefore(translatedAttrs.statements);
8293
- translateVar(tag, propsToExpression(translatedAttrs.properties));
8294
8472
  } else {
8295
8473
  if (_marko_compiler.types.isIdentifier(node.var)) {
8296
8474
  const babelBinding = tag.scope.getBinding(node.var.name);
@@ -8399,7 +8577,8 @@ var html_comment_default = {
8399
8577
  const tagExtra = mergeReferences(tagSection, tag.node, referenceNodes);
8400
8578
  nodeBinding = tagExtra[kNodeBinding$1] = createBinding("#comment", 0, tagSection, void 0, void 0, void 0, void 0, !!tagVar);
8401
8579
  trackDomVarReferences(tag, nodeBinding);
8402
- addSerializeExpr(tagSection, !!tagVar || tagExtra, nodeBinding);
8580
+ if (tagVar) addSerializeExpr(tagSection, true, nodeBinding);
8581
+ addSerializeExpr(tagSection, tagExtra, nodeBinding);
8403
8582
  }
8404
8583
  const write = writeTo(tag);
8405
8584
  if (nodeBinding) visit(tag, 32);
@@ -8511,7 +8690,7 @@ var id_default = {
8511
8690
  const source = initValue(node.var.extra.binding);
8512
8691
  if (valueAttr) {
8513
8692
  const { value } = valueAttr;
8514
- addValue(section, value.extra?.referencedBindings, source, _marko_compiler.types.logicalExpression("||", value, id));
8693
+ addValue(section, value.extra?.referencedBindings, source, _marko_compiler.types.logicalExpression("||", value, evaluate(value).confident ? id : callRuntime("_id", scopeIdentifier, _marko_compiler.types.stringLiteral(getPrefixedScopeAccessor(node.var.extra.binding, getAccessorPrefix().IdFallback)))));
8515
8694
  } else addValue(section, void 0, source, id);
8516
8695
  tag.remove();
8517
8696
  }
@@ -8532,7 +8711,7 @@ var import_default = {
8532
8711
  parse(tag) {
8533
8712
  const { node } = tag;
8534
8713
  const statements = (0, _marko_compiler_babel_utils.parseStatements)(tag.hub.file, node.rawValue, node.start, node.end);
8535
- if (statements.length > 1) throw tag.hub.buildError(statements[1], "The [`<import>` tag](https://markojs.com/docs/syntax/#importing-external-files) takes a single import statement.");
8714
+ if (statements.length > 1) throw tag.hub.buildError(statements[1], "The [`<import>` tag](https://markojs.com/docs/reference/language#import) takes a single import statement.");
8536
8715
  tag.replaceWith(statements[0]);
8537
8716
  },
8538
8717
  parseOptions: {
@@ -8543,7 +8722,7 @@ var import_default = {
8543
8722
  displayText: "import <scope> from \"<path>\"",
8544
8723
  description: "Use to import external modules, follows the same syntax as JavaScript imports.",
8545
8724
  snippet: "import ${2} from \"${1:path}\"",
8546
- descriptionMoreURL: "https://markojs.com/docs/syntax/#importing-external-files"
8725
+ descriptionMoreURL: "https://markojs.com/docs/reference/language#import"
8547
8726
  }]
8548
8727
  };
8549
8728
  //#endregion
@@ -8735,6 +8914,7 @@ var script_default = {
8735
8914
  const section = getSection(tag);
8736
8915
  const { value } = valueAttr;
8737
8916
  const referencedBindings = value.extra?.referencedBindings;
8917
+ if ((_marko_compiler.types.isFunctionExpression(value) || _marko_compiler.types.isArrowFunctionExpression(value)) && _marko_compiler.types.isBlockStatement(value.body) && traverseContains(value.body, isReturnedFunction)) (0, _marko_compiler_babel_utils.diagnosticWarn)(tag, { label: "The value returned from a [`<script>`](https://markojs.com/docs/reference/core-tag#script) body is discarded, so this cleanup function will never run. Register it with [`$signal.onabort`](https://markojs.com/docs/reference/language#signal) or use [`<lifecycle onDestroy>`](https://markojs.com/docs/reference/core-tag#lifecycle) instead." });
8738
8918
  if (isOutputDOM()) {
8739
8919
  const isFunction = _marko_compiler.types.isFunctionExpression(value) || _marko_compiler.types.isArrowFunctionExpression(value);
8740
8920
  let inlineBody = null;
@@ -8775,6 +8955,18 @@ function isAwaitExpression(node) {
8775
8955
  default: return false;
8776
8956
  }
8777
8957
  }
8958
+ function isReturnedFunction(node) {
8959
+ switch (node.type) {
8960
+ case "FunctionDeclaration":
8961
+ case "FunctionExpression":
8962
+ case "ArrowFunctionExpression":
8963
+ case "ClassMethod":
8964
+ case "ObjectMethod":
8965
+ case "ClassPrivateMethod": return skip;
8966
+ case "ReturnStatement": return _marko_compiler.types.isFunctionExpression(node.argument) || _marko_compiler.types.isArrowFunctionExpression(node.argument);
8967
+ default: return false;
8968
+ }
8969
+ }
8778
8970
  function isReturnStatement(node) {
8779
8971
  switch (node.type) {
8780
8972
  case "FunctionDeclaration":
@@ -8789,26 +8981,7 @@ function isReturnStatement(node) {
8789
8981
  }
8790
8982
  //#endregion
8791
8983
  //#region src/translator/core/server.ts
8792
- var server_default = {
8793
- parse(tag) {
8794
- const { node, hub: { file } } = tag;
8795
- const rawValue = node.rawValue;
8796
- const code = rawValue.replace(/^server\s*/, "");
8797
- const start = node.start + (rawValue.length - code.length);
8798
- let body = (0, _marko_compiler_babel_utils.parseStatements)(file, code, start, start + code.length);
8799
- if (body.length === 1 && _marko_compiler.types.isBlockStatement(body[0])) body = body[0].body;
8800
- tag.replaceWith(_marko_compiler.types.markoScriptlet(body, true, "server"));
8801
- },
8802
- parseOptions: {
8803
- statement: true,
8804
- rawOpenTag: true
8805
- },
8806
- autocomplete: [{
8807
- displayText: "server <statement>",
8808
- description: "A JavaScript statement which is only evaluated once your template is loaded on the server.",
8809
- descriptionMoreURL: "https://markojs.com/docs/syntax/#server-javascript"
8810
- }]
8811
- };
8984
+ var server_default = createStatementTag("server");
8812
8985
  //#endregion
8813
8986
  //#region src/translator/util/insertion-context.ts
8814
8987
  const discardsUnknownChildren = /* @__PURE__ */ new Set([
@@ -8947,7 +9120,8 @@ var show_default = {
8947
9120
  snippet: "show=${1:condition}",
8948
9121
  description: "Use to render content that is always mounted but only displayed when the condition is met.",
8949
9122
  descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#show"
8950
- }]
9123
+ }],
9124
+ types: runtime_info_default.name + "/tags/show.d.marko"
8951
9125
  };
8952
9126
  function isSingleNodeBody(tag) {
8953
9127
  let elements = 0;
@@ -8977,36 +9151,18 @@ function assertHasBody(tag) {
8977
9151
  function assertHasValueAttribute(tag) {
8978
9152
  const { node } = tag;
8979
9153
  const [valueAttr] = node.attributes;
8980
- if (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default) throw tag.get("name").buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) requires a [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
9154
+ if (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !(valueAttr.default || valueAttr.name === "value")) throw tag.get("name").buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) requires a [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
8981
9155
  if (node.attributes.length > 1) throw tag.get("name").buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) only supports the [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
8982
9156
  }
8983
9157
  //#endregion
8984
9158
  //#region src/translator/core/static.ts
8985
- var static_default = {
8986
- parse(tag) {
8987
- const { node, hub: { file } } = tag;
8988
- const rawValue = node.rawValue;
8989
- const code = rawValue.replace(/^static\s*/, "");
8990
- const start = node.start + (rawValue.length - code.length);
8991
- let body = (0, _marko_compiler_babel_utils.parseStatements)(file, code, start, start + code.length);
8992
- if (body.length === 1 && _marko_compiler.types.isBlockStatement(body[0])) body = body[0].body;
8993
- tag.replaceWith(_marko_compiler.types.markoScriptlet(body, true));
8994
- },
8995
- parseOptions: {
8996
- statement: true,
8997
- rawOpenTag: true
8998
- },
8999
- autocomplete: [{
9000
- displayText: "static <statement>",
9001
- description: "A JavaScript statement which is only evaluated once your template is loaded.",
9002
- descriptionMoreURL: "https://markojs.com/docs/syntax/#static-javascript"
9003
- }]
9004
- };
9159
+ var static_default = createStatementTag("static");
9005
9160
  function checkStyleInterpolations(tag) {
9006
9161
  const { body } = tag.node.body;
9007
9162
  let stringQuote = "";
9008
9163
  let inComment = false;
9009
9164
  let groupDepth = 0;
9165
+ let urlDepth = 0;
9010
9166
  let blockDepth = 0;
9011
9167
  let valueColon = false;
9012
9168
  let runPlaceholder;
@@ -9021,6 +9177,7 @@ function checkStyleInterpolations(tag) {
9021
9177
  const child = body[i];
9022
9178
  if (_marko_compiler.types.isMarkoPlaceholder(child)) {
9023
9179
  if (stringQuote) throw tag.hub.buildError(child, styleStringMsg);
9180
+ if (urlDepth) throw tag.hub.buildError(child, styleUrlMsg);
9024
9181
  if (!runPlaceholder) {
9025
9182
  runPlaceholder = child;
9026
9183
  runAfterColon = valueColon;
@@ -9048,9 +9205,14 @@ function checkStyleInterpolations(tag) {
9048
9205
  inComment = true;
9049
9206
  j++;
9050
9207
  } else if (c === "\"" || c === "'") stringQuote = c;
9051
- else if (c === "(" || c === "[") groupDepth++;
9052
- else if (c === ")" || c === "]") {
9053
- if (groupDepth) groupDepth--;
9208
+ else if (c === "(" || c === "[") {
9209
+ groupDepth++;
9210
+ if (!urlDepth && cssUrlBefore.test(text.slice(0, j + 1)) && !cssQuotedArg.test(text.slice(j + 1))) urlDepth = groupDepth;
9211
+ } else if (c === ")" || c === "]") {
9212
+ if (groupDepth) {
9213
+ if (urlDepth === groupDepth) urlDepth = 0;
9214
+ groupDepth--;
9215
+ }
9054
9216
  } else if (!groupDepth) switch (c) {
9055
9217
  case ":":
9056
9218
  if (blockDepth) valueColon = true;
@@ -9075,10 +9237,13 @@ const styleInterpolationMsg = "A `${...}` interpolation in a [`<style>` tag](htt
9075
9237
  const styleSelectorMsg = `${styleInterpolationMsg} only resolves in a declaration value, not in a selector or at-rule prelude. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
9076
9238
  const stylePropertyMsg = `${styleInterpolationMsg} cannot be used as a property name. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
9077
9239
  const styleStringMsg = `${styleInterpolationMsg} is not substituted inside a quoted CSS string — the literal text \`var(--…)\` would be rendered instead of the value. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
9240
+ const styleUrlMsg = `${styleInterpolationMsg} is not substituted inside an unquoted \`url()\` — the raw url token consumes the \`var(--…)\` text literally, invalidating the declaration. Move the whole \`url(...)\` into the interpolated value. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
9078
9241
  const styleGluedMsg = `${styleInterpolationMsg} CSS does not re-tokenize, so a unit written directly after it (eg \`\${x}px\`) becomes the invalid \`var(--…)px\`. Move the unit into the interpolated value (so it resolves to eg \`"10px"\`) or use \`calc(var(--…) * 1px)\`.`;
9079
9242
  const styleGluedBeforeMsg = `${styleInterpolationMsg} CSS does not re-tokenize, so text written directly before it (eg \`10\${x}\`) merges with the \`var(--…)\` into a single invalid token. Add whitespace before the interpolation or move the text into the interpolated value.`;
9080
9243
  const cssGluedValue = /^(?:[%.\d]|(?:p[xtc]|in|[cm]m|q|r?em|ex|ch|r?lh|v[whib]|vmin|vmax|fr|deg|g?rad|turn|m?s|k?hz|dp(?:i|cm|px)|cq[whib]|cqmin|cqmax)(?![\w-]))/i;
9081
9244
  const cssGluedBefore = /[\w%]$/;
9245
+ const cssUrlBefore = /(?:^|[^\w-])url\($/i;
9246
+ const cssQuotedArg = /^\s*["']/;
9082
9247
  //#endregion
9083
9248
  //#region src/translator/core/style.ts
9084
9249
  const STYLE_EXT_REG = /^style((?:\.[a-zA-Z0-9$_-]+)+)?/;
@@ -9279,7 +9444,13 @@ var try_default = {
9279
9444
  (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
9280
9445
  (0, _marko_compiler_babel_utils.assertNoParams)(tag);
9281
9446
  (0, _marko_compiler_babel_utils.assertNoAttributes)(tag);
9282
- analyzeAttributeTags(tag);
9447
+ const attrTags = analyzeAttributeTags(tag);
9448
+ if (attrTags) {
9449
+ for (const name in attrTags) if (name !== "@placeholder" && name !== "@catch") {
9450
+ const suggestion = name[1] === "p" ? "`<@placeholder>`" : "`<@catch>`";
9451
+ throw tag.buildCodeFrameError(`The [\`<try>\` tag](https://markojs.com/docs/reference/core-tag#try) only supports the \`<@placeholder>\` and \`<@catch>\` attribute tags, but received \`<${name}>\`. Did you mean ${suggestion}?`);
9452
+ }
9453
+ }
9283
9454
  const section = getOrCreateSection(tag);
9284
9455
  const tagExtra = mergeReferences(section, tag.node, getAllTagReferenceNodes(tag.node));
9285
9456
  tagExtra[kDOMBinding$1] = createBinding("#text", 0, section);
@@ -9403,9 +9574,44 @@ var declaration_default = { translate: { enter(decl) {
9403
9574
  //#endregion
9404
9575
  //#region src/translator/visitors/document-type.ts
9405
9576
  var document_type_default = { translate: { exit(documentType) {
9406
- if (isOutputHTML()) writeTo$1(documentType)`<!${documentType.node.value}>`;
9577
+ if (isOutputHTML()) {
9578
+ writeTo$1(documentType)`<!${documentType.node.value}>`;
9579
+ if (getMarkoOpts().linkAssets && !isBeforeHtmlOrHead(documentType)) writeTo$1(documentType)`${callRuntime("_flush_head")}`;
9580
+ }
9407
9581
  documentType.remove();
9408
9582
  } } };
9583
+ function isBeforeHtmlOrHead(documentType) {
9584
+ let next = documentType.getNextSibling();
9585
+ while (next.node) {
9586
+ if (next.isMarkoTag()) {
9587
+ const { name } = next.node;
9588
+ return name.type === "StringLiteral" && (name.value === "html" || name.value === "head");
9589
+ }
9590
+ next = next.getNextSibling();
9591
+ }
9592
+ return false;
9593
+ }
9594
+ //#endregion
9595
+ //#region src/translator/visitors/export-declaration.ts
9596
+ var export_declaration_default = {
9597
+ analyze(exportDecl) {
9598
+ const { node } = exportDecl;
9599
+ const { source } = node;
9600
+ if (source) {
9601
+ const tagImport = (0, _marko_compiler_babel_utils.resolveTagImport)(exportDecl, source.value);
9602
+ if (tagImport) {
9603
+ (node.extra ??= {}).tagImport = tagImport;
9604
+ const tags = exportDecl.hub.file.metadata.marko.tags;
9605
+ if (!tags.includes(tagImport)) tags.push(tagImport);
9606
+ }
9607
+ }
9608
+ },
9609
+ translate: { exit(exportDecl) {
9610
+ const { node } = exportDecl;
9611
+ const tagImport = node.extra?.tagImport;
9612
+ if (tagImport) node.source.value = tagImport;
9613
+ } }
9614
+ };
9409
9615
  //#endregion
9410
9616
  //#region src/translator/visitors/import-declaration.ts
9411
9617
  const triggerRegExp = /\s*([\w-]+)\s*([^?|]+?)?\s*(?:\?([^|]*?))?\s*(?:\||$)/g;
@@ -9425,16 +9631,17 @@ var import_declaration_default = {
9425
9631
  }
9426
9632
  const loadAttrPath = node.attributes?.length ? importDecl.get("attributes").find((p) => (p.node.key.type === "Identifier" ? p.node.key.name : p.node.key.value) === "load") : void 0;
9427
9633
  if (loadAttrPath) {
9634
+ const loadImport = getLoadImportConfig(loadAttrPath.get("value"));
9635
+ if ((node.importKind || "value") !== "value") throw importDecl.buildCodeFrameError("Invalid load import.");
9636
+ for (const specifier of importDecl.get("specifiers")) if (!_marko_compiler.types.isImportDefaultSpecifier(specifier.node)) throw specifier.buildCodeFrameError("Invalid load import, only a default specifier is allowed.");
9637
+ if (!node.specifiers.some(_marko_compiler.types.isImportDefaultSpecifier)) throw importDecl.buildCodeFrameError("Invalid load import, a default specifier is required.");
9428
9638
  if (!getMarkoOpts().linkAssets) {
9429
9639
  loadAttrPath.remove();
9430
9640
  return;
9431
9641
  }
9432
- (node.extra ??= {}).loadImport = getLoadImportConfig(loadAttrPath.get("value"));
9642
+ (node.extra ??= {}).loadImport = loadImport;
9433
9643
  const { file } = importDecl.hub;
9434
9644
  if (!(tagImport && (0, _marko_compiler_babel_utils.loadFileForImport)(file, value))) throw importDecl.buildCodeFrameError("Unable to resolve marko file for load import.");
9435
- if ((node.importKind || "value") !== "value") throw importDecl.buildCodeFrameError("Invalid load import.");
9436
- for (const specifier of importDecl.get("specifiers")) if (!_marko_compiler.types.isImportDefaultSpecifier(specifier.node)) throw specifier.buildCodeFrameError("Invalid load import, only a default specifier is allowed.");
9437
- if (!node.specifiers.some(_marko_compiler.types.isImportDefaultSpecifier)) throw importDecl.buildCodeFrameError("Invalid load import, a default specifier is required.");
9438
9645
  }
9439
9646
  },
9440
9647
  translate: { exit(importDecl) {
@@ -9452,6 +9659,7 @@ var import_declaration_default = {
9452
9659
  const wrappedName = getOrCreateHtmlLoadWrapped(getReadyId(loadFile), _marko_compiler.types.identifier(local.name), loadFile.opts.filename, loadImport.render ? void 0 : loadImport.triggers);
9453
9660
  for (const ref of binding.referencePaths) ref.replaceWith(_marko_compiler.types.identifier(wrappedName));
9454
9661
  node.source.value = tagImport;
9662
+ node.attributes = void 0;
9455
9663
  return;
9456
9664
  } else if (binding.referencePaths.every((ref) => _marko_compiler.types.isMarkoTag(ref.parent) && ref.parent.extra?.tagNameLoad)) importDecl.remove();
9457
9665
  else {
@@ -9557,7 +9765,7 @@ function isStaticText(node) {
9557
9765
  case "MarkoPlaceholder":
9558
9766
  if (node.escape) {
9559
9767
  const { confident, computed } = evaluate(node.value);
9560
- return confident && isNotVoid(computed);
9768
+ return confident && getHTMLRuntime()._escape(computed) !== "";
9561
9769
  }
9562
9770
  return false;
9563
9771
  }
@@ -9569,7 +9777,7 @@ function getPrevStaticSibling(path) {
9569
9777
  }
9570
9778
  function isEmptyPlaceholder(placeholder) {
9571
9779
  const { confident, computed } = evaluate(placeholder.value);
9572
- return confident && isVoid(computed);
9780
+ return confident && getHTMLRuntime()[placeholder.escape ? "_escape" : "_unescaped"](computed) === "";
9573
9781
  }
9574
9782
  //#endregion
9575
9783
  //#region src/translator/visitors/placeholder.ts
@@ -9582,7 +9790,7 @@ var placeholder_default = {
9582
9790
  const { node } = placeholder;
9583
9791
  const valueExtra = evaluate(node.value);
9584
9792
  const { confident, computed } = valueExtra;
9585
- if (confident && isVoid(computed)) return;
9793
+ if (confident && getHTMLRuntime()[node.escape ? "_escape" : "_unescaped"](computed) === "") return;
9586
9794
  if (!isStaticText(node)) {
9587
9795
  const section = getOrCreateSection(placeholder);
9588
9796
  const nodeBinding = (node.extra ??= {})[kNodeBinding] = createBinding("#text", 0, section);
@@ -9595,9 +9803,10 @@ var placeholder_default = {
9595
9803
  if (isNonHTMLText(placeholder)) return;
9596
9804
  const { node } = placeholder;
9597
9805
  const { confident, computed } = evaluate(node.value);
9598
- if (confident && isVoid(computed)) return;
9806
+ const staticText = confident ? getHTMLRuntime()[node.escape ? "_escape" : "_unescaped"](computed) : void 0;
9807
+ if (staticText === "") return;
9599
9808
  const extra = node.extra || {};
9600
- if (confident && node.escape) writeTo(placeholder)`${getHTMLRuntime()._escape(computed)}`;
9809
+ if (confident && node.escape) writeTo(placeholder)`${staticText}`;
9601
9810
  else {
9602
9811
  const siblingText = extra[kSiblingText];
9603
9812
  if (siblingText === 1 || siblingText === 2) visit(placeholder, 37);
@@ -9620,7 +9829,7 @@ function translateExit(placeholder) {
9620
9829
  if (node.extra?.[kRawText]) injectTextCoercion(value);
9621
9830
  const valueExtra = evaluate(value);
9622
9831
  const { confident, computed } = valueExtra;
9623
- if (confident && isVoid(computed)) {
9832
+ if (confident && getHTMLRuntime()[node.escape ? "_escape" : "_unescaped"](computed) === "") {
9624
9833
  placeholder.remove();
9625
9834
  return;
9626
9835
  }
@@ -9738,8 +9947,10 @@ var referenced_identifier_default = {
9738
9947
  analyze(identifier) {
9739
9948
  const { name } = identifier.node;
9740
9949
  if (identifier.scope.hasBinding(name)) return;
9741
- if (name === "$global") setReferencesScope(identifier);
9742
- else if (name === "$signal") {
9950
+ if (name === "$global") {
9951
+ setReferencesScope(identifier);
9952
+ trackGlobalReference(identifier);
9953
+ } else if (name === "$signal") {
9743
9954
  const section = getOrCreateSection(identifier);
9744
9955
  section.hasAbortSignal = true;
9745
9956
  setReferencesScope(identifier);
@@ -10053,7 +10264,8 @@ var dynamic_tag_default = {
10053
10264
  }
10054
10265
  const bodySection = startSection(tagBody);
10055
10266
  trackParamsReferences(tagBody, 3);
10056
- addSerializeExpr(tagSection, hasVar || tagExtra, nodeBinding);
10267
+ if (hasVar) addSerializeExpr(tagSection, true, nodeBinding);
10268
+ addSerializeExpr(tagSection, tagExtra, nodeBinding);
10057
10269
  if (!hasVar && !node.arguments && !node.attributes.length && !node.body.body.length) tagExtra[kDirectContent] = true;
10058
10270
  if (tagExtra.featureType !== "class" || (0, _marko_compiler_babel_utils.getTagTemplate)(tag)) {
10059
10271
  visit(tag, hasVar ? 49 : 37);
@@ -10154,7 +10366,7 @@ var dynamic_tag_default = {
10154
10366
  if (tag.node.var) {
10155
10367
  const varBinding = tag.node.var.extra.binding;
10156
10368
  tagVarSignal = initValue(varBinding);
10157
- tagVarSignal.register = true;
10369
+ tagVarSignal.register = tagVarSignal.referenced = true;
10158
10370
  tagVarSignal.buildAssignment = (valueSection, value) => {
10159
10371
  const changeArgs = [_marko_compiler.types.memberExpression(getScopeExpression(tagVarSignal.section, valueSection), _marko_compiler.types.stringLiteral(getAccessorPrefix().BranchScopes + getScopeAccessor(nodeBinding)), true), value];
10160
10372
  if (!isOptimize()) changeArgs.push(_marko_compiler.types.stringLiteral(varBinding.name));
@@ -10355,7 +10567,7 @@ function isTagsAPI(file = (0, _marko_compiler_babel_utils.getFile)()) {
10355
10567
  let { featureType } = programExtra;
10356
10568
  if (!featureType) {
10357
10569
  const lookup = (0, _marko_compiler_babel_utils.getTaglibLookup)(file);
10358
- const tagsDir = getTagsDir(file.opts.filename);
10570
+ const tagsDir = getTagsDir(lookup, file.opts.filename);
10359
10571
  const state = {};
10360
10572
  if (tagsDir && !lookup.manualTagsDirs?.has(tagsDir)) addFeature(state, Tags, "Template file within a tags directory", program);
10361
10573
  scanBody(state, program.get("body"));
@@ -10363,24 +10575,10 @@ function isTagsAPI(file = (0, _marko_compiler_babel_utils.getFile)()) {
10363
10575
  }
10364
10576
  return featureType === Tags;
10365
10577
  }
10366
- function getTagsDir(filename) {
10367
- const pathSeparator = /\/|\\/.exec(filename)?.[0];
10368
- if (pathSeparator) {
10369
- let previousIndex = filename.length - 1;
10370
- while (previousIndex > 0) {
10371
- const index = filename.lastIndexOf(pathSeparator, previousIndex);
10372
- switch (previousIndex - index) {
10373
- case 4:
10374
- if (filename.startsWith("tags", index + 1)) return filename.slice(0, index + 5);
10375
- break;
10376
- case 10:
10377
- if (filename.startsWith("components", index + 1)) return false;
10378
- break;
10379
- }
10380
- previousIndex = index - 1;
10381
- }
10382
- }
10383
- return false;
10578
+ function getTagsDir(lookup, filename) {
10579
+ let nearest;
10580
+ for (const dir of lookup.discoveryDirs || []) if (filename.startsWith(dir) && (filename[dir.length] === "/" || filename[dir.length] === "\\") && (!nearest || dir.length > nearest.length)) nearest = dir;
10581
+ return !!nearest && /[/\\]tags$/.test(nearest) && nearest;
10384
10582
  }
10385
10583
  function scanBody(state, body) {
10386
10584
  if (body?.length) for (const child of body) switch (child.type) {
@@ -10668,6 +10866,8 @@ const visitors = extractVisitors({
10668
10866
  Function: function_default,
10669
10867
  ReferencedIdentifier: referenced_identifier_default,
10670
10868
  ImportDeclaration: import_declaration_default,
10869
+ ExportNamedDeclaration: export_declaration_default,
10870
+ ExportAllDeclaration: export_declaration_default,
10671
10871
  MarkoDocumentType: document_type_default,
10672
10872
  MarkoDeclaration: declaration_default,
10673
10873
  MarkoCDATA: cdata_default,