marko 6.3.32 → 6.3.34

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 (63) hide show
  1. package/cheatsheet.md +38 -31
  2. package/dist/common/errors.d.ts +1 -0
  3. package/dist/debug/dom/catch.feat.js +1 -1
  4. package/dist/debug/dom/catch.feat.mjs +1 -1
  5. package/dist/debug/dom/controllable-input.feat.js +1 -1
  6. package/dist/debug/dom/controllable-input.feat.mjs +1 -1
  7. package/dist/debug/dom/controllable-open.feat.js +1 -1
  8. package/dist/debug/dom/controllable-open.feat.mjs +1 -1
  9. package/dist/debug/dom/controllable-select.feat.js +1 -1
  10. package/dist/debug/dom/controllable-select.feat.mjs +1 -1
  11. package/dist/debug/dom/controllable-textarea.feat.js +1 -1
  12. package/dist/debug/dom/controllable-textarea.feat.mjs +1 -1
  13. package/dist/debug/dom/controllable.feat.js +1 -1
  14. package/dist/debug/dom/controllable.feat.mjs +1 -1
  15. package/dist/debug/{dom-CiFITSPN.js → dom-Bj58jt8y.js} +55 -30
  16. package/dist/debug/{dom-BJ93mcSe.mjs → dom-klf8Ec_o.mjs} +55 -30
  17. package/dist/debug/dom.js +3 -1
  18. package/dist/debug/dom.mjs +3 -1
  19. package/dist/debug/html.js +154 -86
  20. package/dist/debug/html.mjs +155 -84
  21. package/dist/dom/catch.feat.js +1 -1
  22. package/dist/dom/catch.feat.mjs +1 -1
  23. package/dist/dom/control-flow.d.ts +3 -1
  24. package/dist/dom/controllable-input.feat.js +1 -1
  25. package/dist/dom/controllable-input.feat.mjs +1 -1
  26. package/dist/dom/controllable-open.feat.js +1 -1
  27. package/dist/dom/controllable-open.feat.mjs +1 -1
  28. package/dist/dom/controllable-select.feat.js +1 -1
  29. package/dist/dom/controllable-select.feat.mjs +1 -1
  30. package/dist/dom/controllable-textarea.feat.js +1 -1
  31. package/dist/dom/controllable-textarea.feat.mjs +1 -1
  32. package/dist/dom/controllable.feat.js +1 -1
  33. package/dist/dom/controllable.feat.mjs +1 -1
  34. package/dist/{dom-Cj4HQ7T_.mjs → dom-6hBvZW7X.mjs} +27 -21
  35. package/dist/{dom-CI-06TZb.js → dom-B-XpL2_H.js} +27 -21
  36. package/dist/dom.js +3 -1
  37. package/dist/dom.mjs +3 -1
  38. package/dist/html/compat.d.ts +6 -2
  39. package/dist/html/writer.d.ts +3 -0
  40. package/dist/html.d.ts +1 -1
  41. package/dist/html.js +104 -65
  42. package/dist/html.mjs +104 -65
  43. package/dist/translator/core/client.d.ts +1 -2
  44. package/dist/translator/core/server.d.ts +1 -2
  45. package/dist/translator/core/static.d.ts +1 -2
  46. package/dist/translator/index.js +430 -294
  47. package/dist/translator/util/branch-tag.d.ts +5 -0
  48. package/dist/translator/util/constants/binding-type.d.ts +1 -0
  49. package/dist/translator/util/references.d.ts +8 -1
  50. package/dist/translator/util/serialize-reasons.d.ts +4 -4
  51. package/dist/translator/util/signals.d.ts +4 -3
  52. package/dist/translator/util/statement-tag.d.ts +2 -0
  53. package/dist/translator/visitors/program/index.d.ts +0 -1
  54. package/index.d.ts +19 -1
  55. package/package.json +5 -4
  56. package/tags/html-comment.d.marko +2 -0
  57. package/tags/html-script.d.marko +2 -0
  58. package/tags/html-style.d.marko +2 -0
  59. package/tags/let.d.marko +2 -2
  60. package/tags/show.d.marko +6 -0
  61. package/tags/try.d.marko +1 -1
  62. package/tags-html.d.ts +6 -1
  63. /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
@@ -601,7 +612,7 @@ function getTagName(tag) {
601
612
  switch (tag.node.name.type) {
602
613
  case "StringLiteral": return tag.node.name.value;
603
614
  case "TemplateLiteral":
604
- if (tag.node.name.quasis.length === 1) return tag.node.name.quasis[0].value.raw;
615
+ if (tag.node.name.quasis.length === 1) return tag.node.name.quasis[0].value.cooked;
605
616
  break;
606
617
  }
607
618
  }
@@ -728,12 +739,8 @@ var Sorted = class {
728
739
  if (!Array.isArray(subset)) return this.findIndex(superset, subset) !== -1;
729
740
  if (!Array.isArray(superset)) return false;
730
741
  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
- }
742
+ if (subLen > superset.length) return false;
743
+ for (let i = subLen; i--;) if (findIndexSorted(this.compare, superset, subset[i]) < i) return false;
737
744
  return true;
738
745
  }
739
746
  };
@@ -983,7 +990,7 @@ function getReadyId(file = (0, _marko_compiler_babel_utils.getFile)()) {
983
990
  return (markoOpts.optimize ? "_" : "ready:") + (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, file.opts.filename);
984
991
  }
985
992
  //#endregion
986
- //#region src/translator/util/get-accessor-char.ts
993
+ //#region src/translator/util/get-accessor-enums.ts
987
994
  function getAccessorPrefix() {
988
995
  return isOptimize() ? accessor_prefix_exports : accessor_prefix_debug_exports;
989
996
  }
@@ -994,6 +1001,8 @@ function getAccessorProp() {
994
1001
  //#region src/translator/util/serialize-reasons.ts
995
1002
  const scopeExprsBySection = /* @__PURE__ */ new WeakMap();
996
1003
  const propExprsBySection = /* @__PURE__ */ new WeakMap();
1004
+ const scopeProvenanceBySection = /* @__PURE__ */ new WeakMap();
1005
+ const propProvenanceBySection = /* @__PURE__ */ new WeakMap();
997
1006
  const serializePropsByBinding = /* @__PURE__ */ new WeakMap();
998
1007
  const serializePropByModifier = {};
999
1008
  function isSameReason(a, b) {
@@ -1003,43 +1012,46 @@ function isForceSerialized(section, prop, prefix) {
1003
1012
  return true === (prop ? section.serializeReasons.get(getPropKey(section, prop, prefix)) : section.serializeReason);
1004
1013
  }
1005
1014
  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);
1015
+ if (reason) {
1016
+ if (reason !== true) addProvenance(section, reason, prop && getPropKey(section, prop, prefix));
1017
+ if (prop) {
1018
+ const key = getPropKey(section, prop, prefix);
1019
+ const curReason = section.serializeReasons.get(key);
1020
+ if (curReason !== true) if (reason === true) forcePropSerialize(section, key);
1021
+ else {
1022
+ const newReason = mergeSerializeReasons(curReason, reason);
1023
+ if (curReason !== newReason) setPropSerializeReason(section, key, newReason);
1024
+ }
1025
+ } else {
1026
+ const curReason = section.serializeReason;
1027
+ if (curReason !== true) if (reason === true) forceSerialize(section);
1028
+ else {
1029
+ const newReason = mergeSerializeReasons(curReason, reason);
1030
+ if (curReason !== newReason) setSerializeReason(section, newReason);
1031
+ }
1020
1032
  }
1021
1033
  }
1022
1034
  }
1023
1035
  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);
1036
+ if (expr) if (prop) {
1037
+ const key = getPropKey(section, prop, prefix);
1038
+ if (expr === true) {
1039
+ if (section.serializeReasons.get(key) !== true) forcePropSerialize(section, key);
1040
+ } else {
1041
+ let curExpr;
1042
+ let curExprs = propExprsBySection.get(section);
1043
+ if (curExprs) curExpr = curExprs.get(key);
1028
1044
  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);
1045
+ curExprs = /* @__PURE__ */ new Map();
1046
+ propExprsBySection.set(section, curExprs);
1037
1047
  }
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);
1048
+ curExprs.set(key, curExpr ? concat(curExpr, expr) : expr);
1042
1049
  }
1050
+ } else if (expr === true) {
1051
+ if (section.serializeReason !== true) forceSerialize(section);
1052
+ } else {
1053
+ const curExpr = scopeExprsBySection.get(section);
1054
+ scopeExprsBySection.set(section, curExpr ? concat(curExpr, expr) : expr);
1043
1055
  }
1044
1056
  }
1045
1057
  function addOwnerSerializeReason(from, to, reason) {
@@ -1093,6 +1105,7 @@ function applySerializeExprs(section) {
1093
1105
  if (propExprs) {
1094
1106
  propExprsBySection.delete(section);
1095
1107
  for (const [key, exprs] of propExprs) {
1108
+ addProvenance(section, getProvenanceForExprs(exprs), key);
1096
1109
  const exprReason = getSerializeSourcesForExprs(exprs);
1097
1110
  if (exprReason) {
1098
1111
  const curReason = section.serializeReasons.get(key);
@@ -1103,8 +1116,9 @@ function applySerializeExprs(section) {
1103
1116
  }
1104
1117
  const scopeExprs = scopeExprsBySection.get(section);
1105
1118
  if (scopeExprs) {
1106
- const exprReason = getSerializeSourcesForExprs(scopeExprs);
1107
1119
  scopeExprsBySection.delete(section);
1120
+ addProvenance(section, getProvenanceForExprs(scopeExprs));
1121
+ const exprReason = getSerializeSourcesForExprs(scopeExprs);
1108
1122
  if (exprReason) {
1109
1123
  const curReason = section.serializeReason;
1110
1124
  const newReason = mergeSerializeReasons(curReason, exprReason);
@@ -1125,6 +1139,26 @@ function finalizeSerializeReason(section) {
1125
1139
  }
1126
1140
  if (newReason && curReason !== newReason) setSerializeReason(section, newReason);
1127
1141
  }
1142
+ const propProvenance = propProvenanceBySection.get(section);
1143
+ if (propProvenance) for (const provenance of propProvenance.values()) addProvenance(section, provenance);
1144
+ }
1145
+ function addProvenance(section, sources, key) {
1146
+ if (!sources) return;
1147
+ if (key) {
1148
+ let provenance = propProvenanceBySection.get(section);
1149
+ if (!provenance) propProvenanceBySection.set(section, provenance = /* @__PURE__ */ new Map());
1150
+ provenance.set(key, mergeSources(provenance.get(key), sources));
1151
+ } else scopeProvenanceBySection.set(section, mergeSources(scopeProvenanceBySection.get(section), sources));
1152
+ }
1153
+ function getProvenanceForExprs(exprs) {
1154
+ let sources;
1155
+ forEach(exprs, (expr) => {
1156
+ sources = mergeSources(sources, getSerializeSourcesForExpr(expr));
1157
+ forEach(expr.referencedBindingsInFunction, (binding) => {
1158
+ sources = mergeSources(sources, getSerializeSourcesForRef(binding));
1159
+ });
1160
+ });
1161
+ return sources;
1128
1162
  }
1129
1163
  function getPropKey(section, prop, prefix) {
1130
1164
  if (isStrOrSym(prop)) {
@@ -1142,12 +1176,10 @@ function getPropKey(section, prop, prefix) {
1142
1176
  }
1143
1177
  }
1144
1178
  function forceSerialize(section) {
1145
- scopeExprsBySection.delete(section);
1146
1179
  setSerializeReason(section, true);
1147
1180
  }
1148
1181
  function forcePropSerialize(section, key) {
1149
1182
  setPropSerializeReason(section, key, true);
1150
- propExprsBySection.get(section)?.delete(key);
1151
1183
  }
1152
1184
  function isStrOrSym(v) {
1153
1185
  switch (typeof v) {
@@ -1544,8 +1576,23 @@ var function_default = { analyze(fn) {
1544
1576
  if (refs === true) registerFunction(fnExtra, true);
1545
1577
  else if (refs.size) getReferencesByFn().set(fnExtra, refs);
1546
1578
  } else if (shouldAlwaysRegister(markoRoot)) registerFunction(fnExtra, true);
1547
- else getReferencesByFn().set(fnExtra, /* @__PURE__ */ new Set([exprRoot.node.extra ??= {}]));
1579
+ else {
1580
+ const refs = /* @__PURE__ */ new Set([exprRoot.node.extra ??= {}]);
1581
+ if (getConstTagVarRefs(markoRoot, refs) === true) registerFunction(fnExtra, true);
1582
+ else getReferencesByFn().set(fnExtra, refs);
1583
+ }
1548
1584
  } };
1585
+ function getConstTagVarRefs(markoRoot, refs, seen = /* @__PURE__ */ new Set()) {
1586
+ const tag = getTagFromMarkoRoot(markoRoot);
1587
+ if (!tag?.node.var || !isCoreTagName(tag, "const") || seen.has(tag.node)) return refs;
1588
+ seen.add(tag.node);
1589
+ const ids = tag.get("var").getOuterBindingIdentifiers();
1590
+ for (const name in ids) {
1591
+ const binding = tag.scope.getBinding(name);
1592
+ if (binding && addBindingRefs(binding, refs, seen) === true) return true;
1593
+ }
1594
+ return refs;
1595
+ }
1549
1596
  function finalizeFunctionRegistry() {
1550
1597
  for (const [fnExtra, exprExtras] of getReferencesByFn()) {
1551
1598
  const reason = resolveSerializeReason(exprExtras);
@@ -1676,7 +1723,10 @@ function addBindingRefs(binding, refs, seen) {
1676
1723
  if (isStaticRoot(markoRoot)) {
1677
1724
  if (getStaticDeclRefs(ref, refs, seen) === true) return true;
1678
1725
  } else if (shouldAlwaysRegister(markoRoot)) return true;
1679
- else refs.add(exprRoot.node.extra ??= {});
1726
+ else {
1727
+ refs.add(exprRoot.node.extra ??= {});
1728
+ if (getConstTagVarRefs(markoRoot, refs, seen) === true) return true;
1729
+ }
1680
1730
  }
1681
1731
  }
1682
1732
  function shouldAlwaysRegister(markoRoot) {
@@ -1976,6 +2026,14 @@ function _resume_branch(scopeId) {
1976
2026
  const branchId = $chunk.context?.[kBranchId];
1977
2027
  if (branchId !== void 0 && branchId !== scopeId) writeScope(scopeId, { [ClosestBranchId$1]: branchId });
1978
2028
  }
2029
+ function deferBranchStart(chunk) {
2030
+ const beforeBranch = chunk.html;
2031
+ chunk.html = "";
2032
+ return beforeBranch;
2033
+ }
2034
+ function applyBranchStart(chunk, beforeBranch, rendered) {
2035
+ chunk.html = beforeBranch + (rendered ? chunk.boundary.state.mark("[", "") : "") + chunk.html;
2036
+ }
1979
2037
  let writeScope = (scopeId, partialScope) => {
1980
2038
  const { state } = $chunk.boundary;
1981
2039
  const target = $chunk.serializeState;
@@ -2135,8 +2193,8 @@ function nonVoidAttr(name, value) {
2135
2193
  }
2136
2194
  return " " + name + attrAssignment(value + "");
2137
2195
  }
2138
- const singleQuoteAttrReplacements = /'|&(?=[#a-zA-Z])/g;
2139
- const doubleQuoteAttrReplacements = /"|&(?=[#a-zA-Z])/g;
2196
+ const singleQuoteAttrReplacements = /['\r]|&(?=[#a-zA-Z])/g;
2197
+ const doubleQuoteAttrReplacements = /["\r]|&(?=[#a-zA-Z])/g;
2140
2198
  const needsQuotedAttr = /["'>\s]|&[#a-zA-Z]|\/$/g;
2141
2199
  function attrAssignment(value) {
2142
2200
  return value ? needsQuotedAttr.test(value) ? value[needsQuotedAttr.lastIndex - 1] === (needsQuotedAttr.lastIndex = 0, "\"") ? "='" + escapeSingleQuotedAttrValue(value) + "'" : "=\"" + escapeDoubleQuotedAttrValue(value) + "\"" : "=" + value : "";
@@ -2145,13 +2203,13 @@ function escapeSingleQuotedAttrValue(value) {
2145
2203
  return singleQuoteAttrReplacements.test(value) ? value.replace(singleQuoteAttrReplacements, replaceUnsafeSingleQuoteAttrChar) : value;
2146
2204
  }
2147
2205
  function replaceUnsafeSingleQuoteAttrChar(match) {
2148
- return match === "'" ? "&#39;" : "&amp;";
2206
+ return match === "'" ? "&#39;" : match === "\r" ? "&#13;" : "&amp;";
2149
2207
  }
2150
2208
  function escapeDoubleQuotedAttrValue(value) {
2151
2209
  return doubleQuoteAttrReplacements.test(value) ? value.replace(doubleQuoteAttrReplacements, replaceUnsafeDoubleQuoteAttrChar) : value;
2152
2210
  }
2153
2211
  function replaceUnsafeDoubleQuoteAttrChar(match) {
2154
- return match === "\"" ? "&#34;" : "&amp;";
2212
+ return match === "\"" ? "&#34;" : match === "\r" ? "&#13;" : "&amp;";
2155
2213
  }
2156
2214
  function normalizedValueMatches(a, b) {
2157
2215
  const value = normalizeStrAttrValue(b);
@@ -2196,7 +2254,8 @@ let _dynamic_tag = (scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, s
2196
2254
  };
2197
2255
  renderNative();
2198
2256
  } else {
2199
- if (shouldResume) _html(state.mark("[", ""));
2257
+ const chunk = void 0;
2258
+ const beforeBranch = shouldResume ? deferBranchStart(chunk) : void 0;
2200
2259
  const render = () => {
2201
2260
  if (renderer) try {
2202
2261
  _set_serialize_reason(shouldResume && inputOrArgs !== void 0 ? 1 : 0);
@@ -2211,7 +2270,10 @@ let _dynamic_tag = (scopeId, accessor, tag, inputOrArgs, content, inputIsArgs, s
2211
2270
  };
2212
2271
  result = shouldResume ? withBranchId(branchId, render) : render();
2213
2272
  rendered = _peek_scope_id() !== branchId;
2214
- if (shouldResume) _html(state.mark("]", scopeId + " " + accessor + (rendered ? " " + branchId : "")));
2273
+ if (beforeBranch !== void 0) {
2274
+ applyBranchStart(chunk, beforeBranch, rendered);
2275
+ _html(state.mark("]", scopeId + " " + accessor + (rendered ? " " + branchId : "")));
2276
+ }
2215
2277
  }
2216
2278
  if (rendered) {
2217
2279
  if (shouldResume) writeScope(scopeId, { [ConditionalRenderer$1 + accessor]: renderer?.["id"] || renderer });
@@ -2678,6 +2740,17 @@ var return_default = {
2678
2740
  (0, _marko_compiler_babel_utils.assertNoParams)(tag);
2679
2741
  assertNoBodyContent(tag);
2680
2742
  (0, _marko_compiler_babel_utils.assertAllowedAttributes)(tag, ["value", "valueChange"]);
2743
+ let valueAttr;
2744
+ let valueChangeAttr;
2745
+ for (const attr of tag.node.attributes) if (_marko_compiler.types.isMarkoAttribute(attr)) {
2746
+ if (attr.name === "value") {
2747
+ if (valueAttr) throw tag.hub.buildError(attr, "Invalid duplicate value attribute.");
2748
+ valueAttr = attr;
2749
+ } else if (attr.name === "valueChange") {
2750
+ if (valueChangeAttr) throw tag.hub.buildError(attr, "Invalid duplicate valueChange attribute.");
2751
+ valueChangeAttr = attr;
2752
+ }
2753
+ }
2681
2754
  const parentTag = getParentTag(tag);
2682
2755
  if (parentTag) {
2683
2756
  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).");
@@ -2986,10 +3059,9 @@ function getSignal(section, referencedBindings, name) {
2986
3059
  section,
2987
3060
  values: [],
2988
3061
  intersection: void 0,
3062
+ forwards: void 0,
2989
3063
  render: [],
2990
- renderReferencedBindings: void 0,
2991
3064
  effect: [],
2992
- effectReferencedBindings: void 0,
2993
3065
  hasHTMLEffect: false,
2994
3066
  build: void 0,
2995
3067
  export: !!exportName,
@@ -3064,12 +3136,13 @@ function isPureMemberForwarder(binding) {
3064
3136
  for (const alias of binding.propertyAliases.values()) if (alias.type !== 6) return true;
3065
3137
  return false;
3066
3138
  }
3067
- function pushMemberForwards(renderStatements, value, alias) {
3139
+ function pushMemberForwards(signal, value, alias) {
3068
3140
  if (isPureMemberForwarder(alias)) {
3069
- for (const [key, child] of alias.propertyAliases) if (child.type !== 6) pushMemberForwards(renderStatements, toMemberExpression(_marko_compiler.types.cloneNode(value, true), key, alias.nullable), child);
3141
+ for (const [key, child] of alias.propertyAliases) if (child.type !== 6) pushMemberForwards(signal, toMemberExpression(_marko_compiler.types.cloneNode(value, true), key, alias.nullable), child);
3070
3142
  } else {
3071
3143
  const aliasSignal = getSignal(alias.section, alias);
3072
- renderStatements.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3144
+ signal.forwards = push(signal.forwards, aliasSignal);
3145
+ signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3073
3146
  scopeIdentifier,
3074
3147
  value,
3075
3148
  ...getTranslatedExtraArgs(aliasSignal)
@@ -3084,32 +3157,35 @@ function getSignalFn(signal) {
3084
3157
  if (isValue) {
3085
3158
  for (const alias of binding.aliases) {
3086
3159
  const aliasSignal = getSignal(alias.section, alias);
3087
- if (signalHasStatements(aliasSignal)) if (alias.excludeProperties !== void 0) {
3088
- const aliasId = _marko_compiler.types.identifier(alias.name);
3089
- let pattern;
3090
- if (alias.restOffset) pattern = _marko_compiler.types.arrayPattern(new Array(alias.restOffset).fill(null).concat(_marko_compiler.types.restElement(aliasId)));
3091
- else {
3092
- const props = [];
3093
- forEach(alias.excludeProperties, (name) => {
3094
- const propId = toPropertyName(name);
3095
- const shorthand = propId.type === "Identifier" && _marko_compiler.types.isValidIdentifier(name);
3096
- props.push(_marko_compiler.types.objectProperty(propId, shorthand ? propId : generateUidIdentifier(name), false, shorthand));
3097
- });
3098
- props.push(_marko_compiler.types.restElement(aliasId));
3099
- pattern = _marko_compiler.types.objectPattern(props);
3100
- }
3101
- signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([pattern], _marko_compiler.types.callExpression(aliasSignal.identifier, [
3160
+ if (signalHasStatements(aliasSignal)) {
3161
+ signal.forwards = push(signal.forwards, aliasSignal);
3162
+ if (alias.excludeProperties !== void 0) {
3163
+ const aliasId = _marko_compiler.types.identifier(alias.name);
3164
+ let pattern;
3165
+ if (alias.restOffset) pattern = _marko_compiler.types.arrayPattern(new Array(alias.restOffset).fill(null).concat(_marko_compiler.types.restElement(aliasId)));
3166
+ else {
3167
+ const props = [];
3168
+ forEach(alias.excludeProperties, (name) => {
3169
+ const propId = toPropertyName(name);
3170
+ const shorthand = propId.type === "Identifier" && _marko_compiler.types.isValidIdentifier(name);
3171
+ props.push(_marko_compiler.types.objectProperty(propId, shorthand ? propId : generateUidIdentifier(name), false, shorthand));
3172
+ });
3173
+ props.push(_marko_compiler.types.restElement(aliasId));
3174
+ pattern = _marko_compiler.types.objectPattern(props);
3175
+ }
3176
+ signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([pattern], _marko_compiler.types.callExpression(aliasSignal.identifier, [
3177
+ scopeIdentifier,
3178
+ aliasId,
3179
+ ...getTranslatedExtraArgs(aliasSignal)
3180
+ ])), [binding.nullable ? _marko_compiler.types.logicalExpression("||", createScopeReadExpression(binding), alias.restOffset ? _marko_compiler.types.arrayExpression([]) : _marko_compiler.types.objectExpression([])) : createScopeReadExpression(binding)])));
3181
+ } else signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3102
3182
  scopeIdentifier,
3103
- aliasId,
3183
+ createScopeReadExpression(binding),
3104
3184
  ...getTranslatedExtraArgs(aliasSignal)
3105
- ])), [binding.nullable ? _marko_compiler.types.logicalExpression("||", createScopeReadExpression(binding), alias.restOffset ? _marko_compiler.types.arrayExpression([]) : _marko_compiler.types.objectExpression([])) : createScopeReadExpression(binding)])));
3106
- } else signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3107
- scopeIdentifier,
3108
- createScopeReadExpression(binding),
3109
- ...getTranslatedExtraArgs(aliasSignal)
3110
- ])));
3185
+ ])));
3186
+ }
3111
3187
  }
3112
- for (const [key, alias] of binding.propertyAliases) if (alias.type !== 6) pushMemberForwards(signal.render, toMemberExpression(createScopeReadExpression(binding), key, binding.nullable), alias);
3188
+ for (const [key, alias] of binding.propertyAliases) if (alias.type !== 6) pushMemberForwards(signal, toMemberExpression(createScopeReadExpression(binding), key, binding.nullable), alias);
3113
3189
  if (assertsHoists) signal.render.push(_marko_compiler.types.expressionStatement(callRuntime("_assert_hoist", createScopeReadExpression(binding))));
3114
3190
  }
3115
3191
  for (const value of signal.values) {
@@ -3228,25 +3304,15 @@ function replaceNullishAndEmptyFunctionsWith0(args) {
3228
3304
  args.length = finalLen || 0;
3229
3305
  return args;
3230
3306
  }
3231
- function addStatement(type, targetSection, referencedBindings, statement, usedReferences, isPure) {
3307
+ function addStatement(type, targetSection, referencedBindings, statement, isPure) {
3232
3308
  const signal = getSignal(targetSection, referencedBindings);
3233
3309
  const statements = signal[type] ??= [];
3234
- const add = type === "effect" ? addEffectReferences : addRenderReferences;
3235
3310
  if (Array.isArray(statement)) statements.push(...statement);
3236
3311
  else statements.push(statement);
3237
- if (usedReferences !== false) if (usedReferences) for (const ref of usedReferences) add(signal, ref);
3238
- else add(signal, referencedBindings);
3239
3312
  if (!isPure || type === "effect") signal.hasSideEffect = true;
3240
3313
  }
3241
- function addEffectReferences(signal, referencedBindings) {
3242
- signal.effectReferencedBindings = bindingUtil.union(signal.effectReferencedBindings, referencedBindings);
3243
- }
3244
- function addRenderReferences(signal, referencedBindings) {
3245
- signal.renderReferencedBindings = bindingUtil.union(signal.renderReferencedBindings, referencedBindings);
3246
- }
3247
3314
  function addValue(targetSection, referencedBindings, signal, value) {
3248
3315
  const parentSignal = getSignal(targetSection, referencedBindings);
3249
- addRenderReferences(parentSignal, referencedBindings);
3250
3316
  parentSignal.values.push({
3251
3317
  signal,
3252
3318
  value
@@ -3255,9 +3321,9 @@ function addValue(targetSection, referencedBindings, signal, value) {
3255
3321
  }
3256
3322
  function buildResumeRegisterKey(section, referencedBindings, type) {
3257
3323
  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}`;
3324
+ if (referencedBindings) if (typeof referencedBindings === "string") name += `*${referencedBindings}`;
3325
+ else if (Array.isArray(referencedBindings)) for (const ref of referencedBindings) name += `_${ref.name}#${ref.id}`;
3326
+ else name += `_${referencedBindings.name}#${referencedBindings.id}`;
3261
3327
  return `${section.id}${name}${type ? "/" + type : ""}`;
3262
3328
  }
3263
3329
  function getResumeRegisterId(section, referencedBindings, type) {
@@ -3287,9 +3353,11 @@ function writeSignals(section) {
3287
3353
  let signalDeclaration;
3288
3354
  if (signal.build) {
3289
3355
  let value = signal.build();
3356
+ const buildsEagerForward = _marko_compiler.types.isIdentifier(value);
3290
3357
  if (!value || !signal.register && _marko_compiler.types.isFunction(value) && _marko_compiler.types.isBlockStatement(value.body) && !value.body.body.length) return;
3291
3358
  if (_marko_compiler.types.isCallExpression(value)) replaceNullishAndEmptyFunctionsWith0(value.arguments);
3292
3359
  if (signal.register) value = callRuntime("_var_resume", _marko_compiler.types.stringLiteral(getResumeRegisterId(section, signal.referencedBindings, "var")), value);
3360
+ if (buildsEagerForward) forEach(signal.forwards, writeSignal);
3293
3361
  const signalDeclarator = _marko_compiler.types.variableDeclarator(signal.identifier, value);
3294
3362
  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
3363
  if (signal.export) signalDeclaration = _marko_compiler.types.exportNamedDeclaration(signalDeclaration);
@@ -3576,15 +3644,15 @@ function replaceRegisteredFunctionNode$1(node) {
3576
3644
  switch (node.type) {
3577
3645
  case "ClassMethod": {
3578
3646
  const replacement = getRegisteredFnExpression$1(node);
3579
- return replacement && _marko_compiler.types.classProperty(node.key, replacement);
3647
+ return replacement && _marko_compiler.types.classProperty(node.key, replacement, void 0, void 0, node.computed, node.static);
3580
3648
  }
3581
3649
  case "ClassPrivateMethod": {
3582
3650
  const replacement = getRegisteredFnExpression$1(node);
3583
- return replacement && _marko_compiler.types.classPrivateProperty(node.key, replacement);
3651
+ return replacement && _marko_compiler.types.classPrivateProperty(node.key, replacement, void 0, node.static);
3584
3652
  }
3585
3653
  case "ObjectMethod": {
3586
3654
  const replacement = getRegisteredFnExpression$1(node);
3587
- return replacement && _marko_compiler.types.objectProperty(node.key, replacement);
3655
+ return replacement && _marko_compiler.types.objectProperty(node.key, replacement, node.computed);
3588
3656
  }
3589
3657
  case "ArrowFunctionExpression":
3590
3658
  case "FunctionExpression": return getRegisteredFnExpression$1(node);
@@ -4093,9 +4161,25 @@ function templateElement(value, tail) {
4093
4161
  }, tail);
4094
4162
  }
4095
4163
  //#endregion
4164
+ //#region src/translator/util/branch-tag.ts
4165
+ function getBranchSectionAccessor(nodeBinding) {
4166
+ return {
4167
+ binding: nodeBinding,
4168
+ prefix: getAccessorPrefix().BranchScopes
4169
+ };
4170
+ }
4171
+ function initBranchSection(bodySection, upstreamExpression, sectionAccessor) {
4172
+ bodySection.isBranch = true;
4173
+ bodySection.upstreamExpression = upstreamExpression;
4174
+ bodySection.sectionAccessor = sectionAccessor;
4175
+ }
4176
+ function resumeOwnerByMarkerWhenStatic(tagSection, bodySection, nodeBinding, statefulReasonKey) {
4177
+ if (isStateSerializeReason(getSerializeReason(tagSection, statefulReasonKey)) && isStaticSerializeReason(getSerializeReason(bodySection, kBranchSerializeReason)) && isStaticSerializeReason(getSerializeReason(tagSection, nodeBinding))) setSectionOwnerResumedByMarker(bodySection);
4178
+ }
4179
+ //#endregion
4096
4180
  //#region src/translator/util/is-event-or-change-handler.ts
4097
4181
  function isEventOrChangeHandler(prop) {
4098
- return /^on[-A-Z][a-zA-Z0-9_$]|[a-zA-Z_$][a-zA-Z0-9_$]*Change$/.test(prop);
4182
+ return /^on[-A-Z]|[a-zA-Z_$][a-zA-Z0-9_$]*Change$/.test(prop);
4099
4183
  }
4100
4184
  //#endregion
4101
4185
  //#region src/translator/util/is-non-html-text.ts
@@ -4160,7 +4244,12 @@ var for_default = {
4160
4244
  if (isAttrTag) return;
4161
4245
  const byAttr = getKnownAttrValues(tag.node).by;
4162
4246
  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}>\`.`);
4163
- 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\`).`);
4247
+ if (byAttr) {
4248
+ const paramNames = /* @__PURE__ */ new Set();
4249
+ for (const param of tag.node.body.params) for (const name in _marko_compiler.types.getBindingIdentifiers(param)) paramNames.add(name);
4250
+ const paramRead = paramNames.size ? findLoopParamRead(byAttr, paramNames) : void 0;
4251
+ 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\`).`);
4252
+ }
4164
4253
  const bodySection = startSection(tagBody);
4165
4254
  if (!bodySection) {
4166
4255
  dropNodes(getAllTagReferenceNodes(tag.node));
@@ -4180,12 +4269,7 @@ var for_default = {
4180
4269
  onFinalizeReferences(() => detectForSelector(bodySection, keyBinding));
4181
4270
  }
4182
4271
  }
4183
- bodySection.sectionAccessor = {
4184
- binding: nodeBinding,
4185
- prefix: getAccessorPrefix().BranchScopes
4186
- };
4187
- bodySection.upstreamExpression = tagExtra;
4188
- bodySection.isBranch = true;
4272
+ initBranchSection(bodySection, tagExtra, getBranchSectionAccessor(nodeBinding));
4189
4273
  if (!isAttrTag && !getOnlyChildParentTagName(tag)) {
4190
4274
  visit(tag, 37);
4191
4275
  enterShallow(tag);
@@ -4219,11 +4303,11 @@ var for_default = {
4219
4303
  const singleChild = bodySection.content?.singleChild && bodySection.content.startType !== 4;
4220
4304
  const branchSerializeReason = getSerializeReason(bodySection, kBranchSerializeReason);
4221
4305
  const markerSerializeReason = getSerializeReason(tagSection, nodeBinding);
4222
- if (isStateSerializeReason(getSerializeReason(tagSection, kStatefulReason$2)) && isStaticSerializeReason(branchSerializeReason) && isStaticSerializeReason(markerSerializeReason)) setSectionOwnerResumedByMarker(bodySection);
4306
+ resumeOwnerByMarkerWhenStatic(tagSection, bodySection, nodeBinding, kStatefulReason$2);
4223
4307
  flushInto(tag);
4224
4308
  writeHTMLResumeStatements(tagBody);
4225
4309
  const forTagArgs = getBaseArgsInForTag(forType, forAttrs);
4226
- const forTagHTMLRuntime = branchSerializeReason ? forTypeToHTMLResumeRuntime(forType) : forTypeToRuntime(forType);
4310
+ const forTagHTMLRuntime = branchSerializeReason ? forTypeToBranchRuntime(forType) : forTypeToRuntime(forType);
4227
4311
  forTagArgs.push(_marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.blockStatement(bodyStatements)));
4228
4312
  if (branchSerializeReason) {
4229
4313
  const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
@@ -4269,7 +4353,7 @@ var for_default = {
4269
4353
  const forType = getForType(node);
4270
4354
  const signal = getSignal(tagSection, nodeRef, "for");
4271
4355
  signal.build = () => {
4272
- return callRuntime(forTypeToDOMRuntime(forType), getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(getBranchRendererArgs(bodySection)));
4356
+ return callRuntime(forTypeToBranchRuntime(forType), getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(getBranchRendererArgs(bodySection)));
4273
4357
  };
4274
4358
  const forAttrs = getKnownAttrValues(node);
4275
4359
  const loopArgs = getBaseArgsInForTag(forType, forAttrs);
@@ -4337,6 +4421,27 @@ function getForType(tag) {
4337
4421
  case "until": return attr.name;
4338
4422
  }
4339
4423
  }
4424
+ function findLoopParamRead(node, names) {
4425
+ switch (node.type) {
4426
+ case "Identifier": return names.has(node.name) ? node : void 0;
4427
+ case "MemberExpression":
4428
+ case "OptionalMemberExpression": return findLoopParamRead(node.object, names) || (node.computed ? findLoopParamRead(node.property, names) : void 0);
4429
+ }
4430
+ if (_marko_compiler.types.isFunction(node) || _marko_compiler.types.isClass(node)) return;
4431
+ for (const key of _marko_compiler.types.VISITOR_KEYS[node.type] || []) {
4432
+ if (key === "typeAnnotation" || key === "typeParameters") continue;
4433
+ if (key === "key" && !node.computed) continue;
4434
+ const value = node[key];
4435
+ if (Array.isArray(value)) for (const child of value) {
4436
+ const found = child?.type && findLoopParamRead(child, names);
4437
+ if (found) return found;
4438
+ }
4439
+ else if (value?.type) {
4440
+ const found = findLoopParamRead(value, names);
4441
+ if (found) return found;
4442
+ }
4443
+ }
4444
+ }
4340
4445
  function getLoopKeyBinding(byAttr, paramsBinding, forType) {
4341
4446
  if (!paramsBinding) return;
4342
4447
  if (byAttr) {
@@ -4379,15 +4484,7 @@ function forTypeToRuntime(type) {
4379
4484
  case "until": return "forUntil";
4380
4485
  }
4381
4486
  }
4382
- function forTypeToHTMLResumeRuntime(type) {
4383
- switch (type) {
4384
- case "of": return "_for_of";
4385
- case "in": return "_for_in";
4386
- case "to": return "_for_to";
4387
- case "until": return "_for_until";
4388
- }
4389
- }
4390
- function forTypeToDOMRuntime(type) {
4487
+ function forTypeToBranchRuntime(type) {
4391
4488
  switch (type) {
4392
4489
  case "of": return "_for_of";
4393
4490
  case "in": return "_for_in";
@@ -4753,7 +4850,7 @@ var native_tag_default = {
4753
4850
  }
4754
4851
  relatedControllable ||= getRelatedControllable(tagName, seen);
4755
4852
  if (relatedControllable && relatedControllable.attrs[1]) hasEventHandlers = true;
4756
- if (node.var || hasDynamicAttributes || hasEventHandlers || textPlaceholders || injectNonce || isDynamicControllable(relatedControllable)) {
4853
+ if (node.var || hasDynamicAttributes || hasEventHandlers || textPlaceholders || injectNonce || seen.content && tagName !== "meta" && !node.body.body.length || isDynamicControllable(relatedControllable)) {
4757
4854
  const tagExtra = node.extra ??= {};
4758
4855
  const tagSection = getOrCreateSection(tag);
4759
4856
  const nodeBinding = tagExtra[kNativeTagBinding] = createBinding("#" + tagName.toLowerCase(), 0, tagSection, void 0, void 0, void 0, void 0, !!node.var);
@@ -4864,6 +4961,7 @@ var native_tag_default = {
4864
4961
  if (hasChangeHandler) addHTMLEffectCall(tagSection, void 0);
4865
4962
  }
4866
4963
  let writeAtStartOfBody;
4964
+ 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");
4867
4965
  if (tagName === "select") {
4868
4966
  if (staticControllable) htmlSelectArgs.set(tag.node, {
4869
4967
  value: staticControllable.attrs[0]?.value || buildUndefined$1(),
@@ -4987,7 +5085,7 @@ var native_tag_default = {
4987
5085
  const isOpenOnly = !!(tagDef && tagDef.parseOptions?.openTagOnly);
4988
5086
  const isTextOnly = isTextOnlyNativeTag(tag);
4989
5087
  const hasChildren = !!tag.node.body.body.length;
4990
- if (injectNonce) addStatement("render", tagSection, void 0, _marko_compiler.types.expressionStatement(callRuntime("_attr_nonce", scopeIdentifier, getScopeAccessorLiteral(nodeBinding))), void 0, true);
5088
+ if (injectNonce) addStatement("render", tagSection, void 0, _marko_compiler.types.expressionStatement(callRuntime("_attr_nonce", scopeIdentifier, getScopeAccessorLiteral(nodeBinding))), true);
4991
5089
  if (staticControllable) {
4992
5090
  const hasChangeHandler = !!staticControllable.attrs[1];
4993
5091
  const defaultHelper = getDOMControllableDefaultHelper(staticControllable);
@@ -5030,14 +5128,14 @@ var native_tag_default = {
5030
5128
  stmt = _marko_compiler.types.expressionStatement(callRuntime(`_attr_${name}_items`, nodeExpr, _marko_compiler.types.objectExpression(props)));
5031
5129
  }
5032
5130
  }
5033
- if (stmt) addStatement("render", tagSection, valueReferences, stmt, void 0, !!meta.dynamicItems);
5131
+ if (stmt) addStatement("render", tagSection, valueReferences, stmt, !!meta.dynamicItems);
5034
5132
  }
5035
5133
  break;
5036
5134
  }
5037
5135
  default:
5038
5136
  if (confident) break;
5039
5137
  else if (isEventHandler(name)) addStatement("effect", tagSection, valueReferences, _marko_compiler.types.expressionStatement(callRuntime("_on", createScopeReadExpression(nodeBinding), _marko_compiler.types.stringLiteral(getEventHandlerName(name)), value)));
5040
- else addStatement("render", tagSection, valueReferences, _marko_compiler.types.expressionStatement(callRuntime("_attr", createScopeReadExpression(nodeBinding), _marko_compiler.types.stringLiteral(name), value)), void 0, true);
5138
+ else addStatement("render", tagSection, valueReferences, _marko_compiler.types.expressionStatement(callRuntime("_attr", createScopeReadExpression(nodeBinding), _marko_compiler.types.stringLiteral(name), value)), true);
5041
5139
  break;
5042
5140
  }
5043
5141
  }
@@ -5049,9 +5147,9 @@ var native_tag_default = {
5049
5147
  if (skipExpression) addStatement("render", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime(canHaveAttrContent ? "_attrs_partial_content" : "_attrs_partial", scopeIdentifier, visitAccessor, spreadExpression, skipExpression, controllable && importRuntime(controllable))));
5050
5148
  else addStatement("render", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime(canHaveAttrContent ? "_attrs_content" : "_attrs", scopeIdentifier, visitAccessor, spreadExpression, controllable && importRuntime(controllable))));
5051
5149
  enableControllable(controllableFeatureFor(staticName));
5052
- addStatement("effect", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_attrs_script", scopeIdentifier, visitAccessor)), false);
5150
+ addStatement("effect", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_attrs_script", scopeIdentifier, visitAccessor)));
5053
5151
  }
5054
- if (staticContentAttr) addStatement("render", tagSection, staticContentAttr.value.extra?.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_attr_content", scopeIdentifier, visitAccessor, staticContentAttr.value)), void 0, true);
5152
+ if (staticContentAttr) addStatement("render", tagSection, staticContentAttr.value.extra?.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_attr_content", scopeIdentifier, visitAccessor, staticContentAttr.value)), true);
5055
5153
  },
5056
5154
  exit(tag) {
5057
5155
  const nodeBinding = tag.node.extra[kNativeTagBinding];
@@ -5059,7 +5157,7 @@ var native_tag_default = {
5059
5157
  const tagName = getCanonicalTagName(tag);
5060
5158
  if (!openTagOnly) if (tagName !== "textarea" && isTextOnlyNativeTag(tag)) {
5061
5159
  const textLiteral = bodyToTextLiteral(tag.node.body);
5062
- if (!_marko_compiler.types.isStringLiteral(textLiteral)) addStatement("render", getSection(tag), textLiteral.extra?.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_text_content", createScopeReadExpression(nodeBinding), textLiteral)), void 0, true);
5160
+ if (!_marko_compiler.types.isStringLiteral(textLiteral)) addStatement("render", getSection(tag), textLiteral.extra?.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_text_content", createScopeReadExpression(nodeBinding), textLiteral)), true);
5063
5161
  } else tag.insertBefore(tag.node.body.body).forEach((child) => child.skip());
5064
5162
  tag.remove();
5065
5163
  }
@@ -5437,7 +5535,7 @@ function trackDelimitedAttrObjectProperties(obj, meta) {
5437
5535
  if (prop.key.type === "Identifier") key = prop.key.name;
5438
5536
  else {
5439
5537
  const keyEval = evaluate(prop.key);
5440
- if (keyEval.confident && typeof keyEval.computed === "string" && !/\s/.test(keyEval.computed)) key = keyEval.computed + "";
5538
+ if (keyEval.confident && typeof keyEval.computed === "string" && !/^$|\s/.test(keyEval.computed)) key = keyEval.computed + "";
5441
5539
  else {
5442
5540
  (dynamicProps ||= []).push(prop);
5443
5541
  continue;
@@ -5529,16 +5627,9 @@ const IfTag = {
5529
5627
  visit(ifTag, 37);
5530
5628
  enterShallow(ifTag);
5531
5629
  }
5532
- const sectionAccessor = {
5533
- binding: getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length),
5534
- prefix: getAccessorPrefix().BranchScopes
5535
- };
5630
+ const sectionAccessor = getBranchSectionAccessor(getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length));
5536
5631
  for (const [branchTag, branchBodySection] of branches) {
5537
- if (branchBodySection) {
5538
- branchBodySection.isBranch = true;
5539
- branchBodySection.upstreamExpression = ifTagExtra;
5540
- branchBodySection.sectionAccessor = sectionAccessor;
5541
- }
5632
+ if (branchBodySection) initBranchSection(branchBodySection, ifTagExtra, sectionAccessor);
5542
5633
  if (branchTag.node.attributes.length) mergeReferenceNodes.push(branchTag.node.attributes[0].value);
5543
5634
  }
5544
5635
  mergeReferences(ifTagSection, ifTag.node, mergeReferenceNodes);
@@ -5558,9 +5649,10 @@ const IfTag = {
5558
5649
  const tagBody = tag.get("body");
5559
5650
  const bodySection = getSectionForBody(tagBody);
5560
5651
  if (bodySection) {
5561
- const [[ifTag]] = getBranches(tag);
5652
+ const branches = getBranches(tag);
5653
+ const [ifTag] = branches[0];
5562
5654
  const ifTagSection = getSection(ifTag);
5563
- if (isStateSerializeReason(getSerializeReason(ifTagSection, kStatefulReason$1)) && isStaticSerializeReason(getSerializeReason(bodySection, kBranchSerializeReason)) && isStaticSerializeReason(getSerializeReason(ifTagSection, getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection)))) setSectionOwnerResumedByMarker(bodySection);
5655
+ resumeOwnerByMarkerWhenStatic(ifTagSection, bodySection, getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length), kStatefulReason$1);
5564
5656
  flushInto(tag);
5565
5657
  writeHTMLResumeStatements(tagBody);
5566
5658
  }
@@ -5568,22 +5660,22 @@ const IfTag = {
5568
5660
  const branches = getBranches(tag);
5569
5661
  const [ifTag] = branches[0];
5570
5662
  const ifTagSection = getSection(ifTag);
5571
- const nodeBinding = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection);
5572
- const onlyChildParentTagName = getOnlyChildParentTagName(ifTag);
5663
+ const nodeBinding = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length);
5664
+ const onlyChildParentTagName = getOnlyChildParentTagName(ifTag, branches.length);
5573
5665
  const markerSerializeReason = getSerializeReason(ifTagSection, nodeBinding);
5574
5666
  const nextTag = tag.getNextSibling();
5575
5667
  let branchSerializeReasons;
5576
5668
  let statement;
5577
5669
  let singleChild = true;
5578
- for (const [, branchBody] of branches) if (!(branchBody?.content?.singleChild && branchBody.content.startType !== 4)) {
5670
+ for (const [, branchBodySection] of branches) if (!(branchBodySection?.content?.singleChild && branchBodySection.content.startType !== 4)) {
5579
5671
  singleChild = false;
5580
5672
  break;
5581
5673
  }
5582
5674
  for (let i = branches.length; i--;) {
5583
- const [branchTag, branchBody] = branches[i];
5675
+ const [branchTag, branchBodySection] = branches[i];
5584
5676
  const bodyStatements = branchTag.node.body.body;
5585
- if (branchBody) {
5586
- const branchSerializeReason = getSerializeReason(branchBody, kBranchSerializeReason);
5677
+ if (branchBodySection) {
5678
+ const branchSerializeReason = getSerializeReason(branchBodySection, kBranchSerializeReason);
5587
5679
  if (branchSerializeReason) {
5588
5680
  if (branchSerializeReasons !== true) if (branchSerializeReason === true || branchSerializeReason.state) branchSerializeReasons = true;
5589
5681
  else if (branchSerializeReasons) branchSerializeReasons = addSorted(compareSources, branchSerializeReasons, branchSerializeReason);
@@ -5622,7 +5714,7 @@ const IfTag = {
5622
5714
  const [ifTag] = branches[0];
5623
5715
  const ifTagSection = getSection(ifTag);
5624
5716
  const ifTagExtra = branches[0][0].node.extra;
5625
- const nodeRef = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection);
5717
+ const nodeRef = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length);
5626
5718
  let expr = _marko_compiler.types.numericLiteral(branches.length);
5627
5719
  for (let i = branches.length; i--;) {
5628
5720
  const [branchTag, branchBodySection] = branches[i];
@@ -5685,7 +5777,7 @@ function flattenTextOnlyConditional(rootTag) {
5685
5777
  const [attr] = node.attributes;
5686
5778
  if (isCoreTagName(tag, "else")) {
5687
5779
  if (node.attributes.length > 1 || attr && (!_marko_compiler.types.isMarkoAttribute(attr) || attr.name !== "if")) return;
5688
- } else if (node.attributes.length !== 1 || !_marko_compiler.types.isMarkoAttribute(attr) || !attr.default) return;
5780
+ } else if (node.attributes.length !== 1 || !_marko_compiler.types.isMarkoAttribute(attr) || !(attr.default || attr.name === "value")) return;
5689
5781
  for (const child of body) if (_marko_compiler.types.isMarkoText(child)) {
5690
5782
  if (_escape(child.value) !== child.value) return;
5691
5783
  } else if (!_marko_compiler.types.isMarkoPlaceholder(child) || !child.escape) return;
@@ -5741,7 +5833,7 @@ function assertHasBody$1(tag) {
5741
5833
  function assertHasValueAttribute$1(tag) {
5742
5834
  const { node } = tag;
5743
5835
  const [valueAttr] = node.attributes;
5744
- 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).`);
5836
+ 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).`);
5745
5837
  if (node.attributes.length > 1) {
5746
5838
  const start = node.attributes[1].loc?.start;
5747
5839
  const end = node.attributes[node.attributes.length - 1].loc?.end;
@@ -5920,14 +6012,17 @@ function getChangeHandler(tag, attr) {
5920
6012
  if (_marko_compiler.types.isIdentifier(attr.value)) {
5921
6013
  const binding = tag.scope.getBinding(attr.value.name);
5922
6014
  if (!binding) return _marko_compiler.types.markoAttribute(changeAttrName, buildChangeHandlerFunction(attr.value, modifier));
5923
- const existingChangedAttr = BINDING_CHANGE_HANDLER.get(binding.identifier);
6015
+ const modifierKey = modifier?.name ?? "";
6016
+ let handlerByModifier = BINDING_CHANGE_HANDLER.get(binding.identifier);
6017
+ if (!handlerByModifier) BINDING_CHANGE_HANDLER.set(binding.identifier, handlerByModifier = /* @__PURE__ */ new Map());
6018
+ const existingChangedAttr = handlerByModifier.get(modifierKey);
5924
6019
  if (!existingChangedAttr) {
5925
6020
  const bindingIdentifierPath = binding.path.getOuterBindingIdentifierPaths()[binding.identifier.name];
5926
6021
  let changeAttrExpr = bindingIdentifierPath ? bindingIdentifierPath.parentPath === binding.path ? buildChangeHandlerFunction(attr.value, modifier) : bindingIdentifierPath.parentPath.isObjectProperty() ? getChangeHandlerFromObjectPattern(bindingIdentifierPath.parentPath) : void 0 : void 0;
5927
6022
  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.");
5928
6023
  if (modifier && _marko_compiler.types.isIdentifier(changeAttrExpr)) changeAttrExpr = _marko_compiler.types.logicalExpression("&&", changeAttrExpr, buildModifierForwarder(_marko_compiler.types.cloneNode(changeAttrExpr), modifier));
5929
6024
  const changeHandlerAttr = _marko_compiler.types.markoAttribute(changeAttrName, changeAttrExpr);
5930
- BINDING_CHANGE_HANDLER.set(binding.identifier, changeHandlerAttr);
6025
+ handlerByModifier.set(modifierKey, changeHandlerAttr);
5931
6026
  return changeHandlerAttr;
5932
6027
  }
5933
6028
  if (existingChangedAttr.type === "Identifier") return _marko_compiler.types.markoAttribute(changeAttrName, withPreviousLocation(_marko_compiler.types.identifier(existingChangedAttr.name), attr.value));
@@ -5935,7 +6030,7 @@ function getChangeHandler(tag, attr) {
5935
6030
  if (!(markoRoot?.isMarkoTag() || markoRoot?.isMarkoTagBody())) throw tag.hub.buildError(attr.value, "Unable to bind to value.");
5936
6031
  const changeHandlerId = generateUid(changeAttrName);
5937
6032
  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));
5938
- BINDING_CHANGE_HANDLER.set(binding.identifier, existingChangedAttr.value = _marko_compiler.types.identifier(changeHandlerId));
6033
+ handlerByModifier.set(modifierKey, existingChangedAttr.value = _marko_compiler.types.identifier(changeHandlerId));
5939
6034
  if (markoRoot.isMarkoTag()) markoRoot.insertAfter(changeHandlerConst);
5940
6035
  else markoRoot.unshiftContainer("body", changeHandlerConst);
5941
6036
  return _marko_compiler.types.markoAttribute(changeAttrName, withPreviousLocation(_marko_compiler.types.identifier(changeHandlerId), attr.value));
@@ -6248,7 +6343,8 @@ function knownTagAnalyze(tag, contentSection, propTree) {
6248
6343
  const varExpr = tagExtra.defineBodySection ? contentSection.returnValueExpr : mapParamReasonToExpr(exprs, contentSection.returnSerializeReason && (contentSection.returnSerializeReason === true || !!contentSection.returnSerializeReason.state || contentSection.returnSerializeReason.param));
6249
6344
  varBinding.scopeOffset = tagExtra[kChildOffsetScopeBinding$1] = createBinding("#scopeOffset", 0, section);
6250
6345
  setBindingDownstream(varBinding, varExpr);
6251
- addSerializeExpr(section, mutatesTagVar || varExpr, childScopeBinding);
6346
+ if (mutatesTagVar) addSerializeExpr(section, true, childScopeBinding);
6347
+ addSerializeExpr(section, varExpr, childScopeBinding);
6252
6348
  }
6253
6349
  addSerializeExpr(section, fromIter(attrExprs), childScopeBinding);
6254
6350
  }
@@ -6555,7 +6651,7 @@ function writeParamsToSignals(tag, propTree, importAlias, info) {
6555
6651
  const argExport = propTree.props[i];
6556
6652
  if (argExport) {
6557
6653
  const argExportIdentifier = info.getBindingIdentifier(argExport.binding, `${importAlias}_param_${i}`);
6558
- addStatement("render", info.tagSection, arg.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(argExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), arg])), void 0, true);
6654
+ addStatement("render", info.tagSection, arg.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(argExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), arg])), true);
6559
6655
  }
6560
6656
  i++;
6561
6657
  }
@@ -6568,36 +6664,31 @@ function applyAttrObject(tag, propTree, tagInputIdentifier, info) {
6568
6664
  let translatedProps = propsToExpression(translatedAttrs.properties);
6569
6665
  if (translatedAttrs.statements.length) addStatement("render", info.tagSection, referencedBindings, translatedAttrs.statements);
6570
6666
  if ((0, _marko_compiler_babel_utils.isAttributeTag)(tag)) {
6571
- translatedProps = _marko_compiler.types.objectExpression(translatedAttrs.properties);
6572
- const attrTagName = getTagName(tag);
6573
- const parentTag = tag.parentPath;
6574
- if (analyzeAttributeTags(parentTag)?.[attrTagName]?.repeated) {
6575
- let attrTagCallsForTag = (info.attrTagCallsByTag ||= /* @__PURE__ */ new Map()).get(parentTag);
6576
- if (!attrTagCallsForTag) info.attrTagCallsByTag.set(parentTag, attrTagCallsForTag = /* @__PURE__ */ new Map());
6577
- const attrTagCall = attrTagCallsForTag.get(attrTagName);
6578
- if (attrTagCall) {
6579
- attrTagCall.expression = callRuntime("attrTags", attrTagCall.expression, translatedProps);
6580
- return;
6581
- } else attrTagCallsForTag.set(attrTagName, translatedProps = _marko_compiler.types.parenthesizedExpression(callRuntime("attrTag", translatedProps)));
6582
- } else translatedProps = callRuntime("attrTag", translatedProps);
6667
+ const repeated = analyzeAttributeTags(tag.parentPath)?.[getTagName(tag)]?.repeated;
6668
+ const mergedProps = getAttrTagProps(tag, repeated, _marko_compiler.types.objectExpression(translatedAttrs.properties), info);
6669
+ if (!mergedProps) return;
6670
+ translatedProps = mergedProps;
6583
6671
  }
6584
- addStatement("render", info.tagSection, referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(tagInputIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), translatedProps])), void 0, true);
6672
+ addStatement("render", info.tagSection, referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(tagInputIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), translatedProps])), true);
6585
6673
  }
6586
6674
  function translateAttrTag(tag, attrTagMeta, info, statements) {
6587
6675
  const translatedAttrs = translateAttrs(tag, true, void 0, statements);
6588
- let translatedProps = _marko_compiler.types.objectExpression(translatedAttrs.properties);
6676
+ return getAttrTagProps(tag, attrTagMeta.repeated, _marko_compiler.types.objectExpression(translatedAttrs.properties), info);
6677
+ }
6678
+ function getAttrTagProps(tag, repeated, translatedProps, info) {
6679
+ if (!repeated) return callRuntime("attrTag", translatedProps);
6589
6680
  const attrTagName = getTagName(tag);
6590
6681
  const parentTag = tag.parentPath;
6591
- if (attrTagMeta.repeated) {
6592
- let attrTagCallsForTag = (info.attrTagCallsByTag ||= /* @__PURE__ */ new Map()).get(parentTag);
6593
- if (!attrTagCallsForTag) info.attrTagCallsByTag.set(parentTag, attrTagCallsForTag = /* @__PURE__ */ new Map());
6594
- const attrTagCall = attrTagCallsForTag.get(attrTagName);
6595
- if (attrTagCall) {
6596
- attrTagCall.expression = callRuntime("attrTags", attrTagCall.expression, translatedProps);
6597
- return;
6598
- } else attrTagCallsForTag.set(attrTagName, translatedProps = _marko_compiler.types.parenthesizedExpression(callRuntime("attrTag", translatedProps)));
6599
- } else translatedProps = callRuntime("attrTag", translatedProps);
6600
- return translatedProps;
6682
+ let attrTagCallsForTag = (info.attrTagCallsByTag ||= /* @__PURE__ */ new Map()).get(parentTag);
6683
+ if (!attrTagCallsForTag) info.attrTagCallsByTag.set(parentTag, attrTagCallsForTag = /* @__PURE__ */ new Map());
6684
+ const attrTagCall = attrTagCallsForTag.get(attrTagName);
6685
+ if (attrTagCall) {
6686
+ attrTagCall.expression = callRuntime("attrTags", attrTagCall.expression, translatedProps);
6687
+ return;
6688
+ }
6689
+ const wrappedProps = _marko_compiler.types.parenthesizedExpression(callRuntime("attrTag", translatedProps));
6690
+ attrTagCallsForTag.set(attrTagName, wrappedProps);
6691
+ return wrappedProps;
6601
6692
  }
6602
6693
  function writeAttrsToSignals(tag, propTree, importAlias, info) {
6603
6694
  if (!propTree.props) {
@@ -6691,7 +6782,7 @@ function writeAttrsToSignals(tag, propTree, importAlias, info) {
6691
6782
  else {
6692
6783
  remaining.delete("content");
6693
6784
  const directContent = !bodySection.params;
6694
- addStatement("render", info.tagSection, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(contentExport.binding, `${importAlias}_content`, directContent), [createScopeReadExpression(info.childScopeBinding, info.tagSection), bodyValue])), void 0, true);
6785
+ addStatement("render", info.tagSection, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(contentExport.binding, `${importAlias}_content`, directContent), [createScopeReadExpression(info.childScopeBinding, info.tagSection), bodyValue])), true);
6695
6786
  }
6696
6787
  }
6697
6788
  }
@@ -6719,13 +6810,13 @@ function writeAttrsToSignals(tag, propTree, importAlias, info) {
6719
6810
  const childAttrExports = getKnownFromPropTree(propTree, attr.name);
6720
6811
  const attrExportIdentifier = info.getBindingIdentifier(childAttrExports.binding, `${importAlias}_${attr.name}`);
6721
6812
  remaining.delete(attr.name);
6722
- addStatement("render", info.tagSection, attr.value.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(attrExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), attr.value])), void 0, true);
6813
+ addStatement("render", info.tagSection, attr.value.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(attrExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), attr.value])), true);
6723
6814
  }
6724
6815
  if (knownSpread) for (const prop of remaining) {
6725
6816
  const childAttrExports = getKnownFromPropTree(propTree, prop);
6726
6817
  const attrExportIdentifier = info.getBindingIdentifier(childAttrExports.binding, `${importAlias}_${prop}`);
6727
6818
  const propBinding = knownSpread.binding.propertyAliases.get(prop);
6728
- addStatement("render", info.tagSection, propBinding, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(attrExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), createScopeReadExpression(propBinding, info.tagSection)])), void 0, true);
6819
+ addStatement("render", info.tagSection, propBinding, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(attrExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), createScopeReadExpression(propBinding, info.tagSection)])), true);
6729
6820
  }
6730
6821
  else if (spreadProps && (remaining.size || propTree.rest && !propTree.rest.props)) {
6731
6822
  const spreadExpr = propsToExpression(spreadProps.reverse());
@@ -6748,7 +6839,7 @@ function writeAttrsToSignals(tag, propTree, importAlias, info) {
6748
6839
  props.push(_marko_compiler.types.objectProperty(propId, shorthand ? propId : generateUidIdentifier(name), false, shorthand));
6749
6840
  });
6750
6841
  props.push(_marko_compiler.types.restElement(restId));
6751
- addStatement("render", info.tagSection, tagReferencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(propTree.rest.binding, importAlias + "_$rest"), [createScopeReadExpression(info.childScopeBinding, info.tagSection), _marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.objectPattern(props)], restId), [spreadId])])), void 0, true);
6842
+ addStatement("render", info.tagSection, tagReferencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(propTree.rest.binding, importAlias + "_$rest"), [createScopeReadExpression(info.childScopeBinding, info.tagSection), _marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.objectPattern(props)], restId), [spreadId])])), true);
6752
6843
  }
6753
6844
  } else {
6754
6845
  for (const name of remaining) {
@@ -6756,7 +6847,7 @@ function writeAttrsToSignals(tag, propTree, importAlias, info) {
6756
6847
  const attrExportIdentifier = info.getBindingIdentifier(childAttrExports.binding, `${importAlias}_${name}`);
6757
6848
  addStatement("render", info.tagSection, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(attrExportIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection)])));
6758
6849
  }
6759
- if (propTree.rest && !propTree.rest.props) addStatement("render", info.tagSection, tagReferencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(propTree.rest.binding, importAlias + "_$rest"), [createScopeReadExpression(info.childScopeBinding, info.tagSection), _marko_compiler.types.objectExpression(restProps || [])])), void 0, true);
6850
+ if (propTree.rest && !propTree.rest.props) addStatement("render", info.tagSection, tagReferencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(propTree.rest.binding, importAlias + "_$rest"), [createScopeReadExpression(info.childScopeBinding, info.tagSection), _marko_compiler.types.objectExpression(restProps || [])])), true);
6760
6851
  }
6761
6852
  }
6762
6853
  function mapParamReasonToExpr(exprs, reason) {
@@ -6772,11 +6863,11 @@ function mapParamReasonToExpr(exprs, reason) {
6772
6863
  }
6773
6864
  }
6774
6865
  function mapParamBindingToExpr(exprs, binding) {
6775
- const isRest = binding.property === void 0 && binding.excludeProperties !== void 0;
6866
+ const isWholeAlias = binding.property === void 0 && binding.upstreamAlias !== void 0;
6776
6867
  const props = [];
6777
- let curBinding = isRest ? binding.upstreamAlias : binding;
6778
- while (curBinding && curBinding.property !== void 0) {
6779
- props.push(curBinding.property);
6868
+ let curBinding = isWholeAlias ? binding.upstreamAlias : binding;
6869
+ while (curBinding && (curBinding.property !== void 0 || curBinding.upstreamAlias)) {
6870
+ if (curBinding.property !== void 0) props.push(curBinding.property);
6780
6871
  curBinding = curBinding.upstreamAlias;
6781
6872
  }
6782
6873
  let curExpr = exprs;
@@ -6785,7 +6876,7 @@ function mapParamBindingToExpr(exprs, binding) {
6785
6876
  if (!nestedExpr) return curExpr.value;
6786
6877
  curExpr = nestedExpr;
6787
6878
  }
6788
- if (isRest) {
6879
+ if (isWholeAlias) {
6789
6880
  let result = curExpr.value;
6790
6881
  if (curExpr.known) {
6791
6882
  for (const key in curExpr.known) if (!includes(binding.excludeProperties, key)) result = concat(result, curExpr.known[key].value);
@@ -6814,6 +6905,11 @@ function getRootSection(section) {
6814
6905
  //#endregion
6815
6906
  //#region src/translator/util/references.ts
6816
6907
  const kBranchSerializeReason = Symbol("branch serialize reason");
6908
+ const globalSources = {
6909
+ state: void 0,
6910
+ param: void 0,
6911
+ global: true
6912
+ };
6817
6913
  const [getBindings] = createProgramState(() => /* @__PURE__ */ new Set());
6818
6914
  const [getNextBindingId, setNextBindingId] = createProgramState(() => 0);
6819
6915
  function createBinding(name, type, refSection, upstreamAlias, property, excludeProperties, loc = null, refDeclared = false) {
@@ -6872,11 +6968,10 @@ function getOrCreatePropertyAlias(binding, property) {
6872
6968
  function trackDomVarReferences(tag, binding) {
6873
6969
  const tagVar = tag.node.var;
6874
6970
  if (!tagVar) return;
6875
- if (!_marko_compiler.types.isIdentifier(tagVar)) throw tag.get("var").buildCodeFrameError("Tag variables on native elements cannot be destructured.");
6876
6971
  const babelBinding = tag.scope.getBinding(tagVar.name);
6877
6972
  const section = getOrCreateSection(tag);
6878
6973
  binding.originalName = tagVar.name;
6879
- 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.");
6974
+ 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.`);
6880
6975
  for (const ref of babelBinding.referencePaths) {
6881
6976
  const refSection = getOrCreateSection(ref);
6882
6977
  const invoked = isInvokedFunction(ref);
@@ -6954,7 +7049,7 @@ function trackReferencesForBinding(babelBinding, binding) {
6954
7049
  for (const ref of referencePaths) {
6955
7050
  const refSection = getOrCreateSection(ref);
6956
7051
  const markoRoot = getMarkoRoot(ref);
6957
- if (markoRoot?.type === "MarkoAttribute" && markoRoot.parentPath === babelBinding.path) throw ref.buildCodeFrameError(`Tag variable circular references are not supported.`);
7052
+ 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.`);
6958
7053
  else if (isReferenceHoisted(babelBinding.path, ref)) {
6959
7054
  const invoked = isInvokedFunction(ref);
6960
7055
  if (invoked) setReferencesScope(ref);
@@ -6976,8 +7071,8 @@ function trackReferencesForBinding(babelBinding, binding) {
6976
7071
  }
6977
7072
  }
6978
7073
  for (const ref of constantViolations) {
6979
- if (ref.type === "MarkoTag") throw ref.get("var").buildCodeFrameError(`Duplicate declaration ${JSON.stringify(binding.name)}`);
6980
- if (isReferenceHoisted(babelBinding.path, ref)) throw ref.buildCodeFrameError("Cannot assign to hoisted tag variable.");
7074
+ if (ref.type === "MarkoTag") throw ref.get("var").buildCodeFrameError(`Duplicate declaration of \`${binding.name}\`.`);
7075
+ 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.`);
6981
7076
  if (ref.isUpdateExpression()) trackAssignment(ref.get("argument"), binding);
6982
7077
  else if (ref.isAssignmentExpression()) {
6983
7078
  trackAssignment(ref.get("left"), binding);
@@ -6990,7 +7085,7 @@ function trackReferencesForBinding(babelBinding, binding) {
6990
7085
  }
6991
7086
  function trackAssignment(assignment, binding) {
6992
7087
  const fnParent = getFnParent(assignment);
6993
- if (!fnParent) throw assignment.buildCodeFrameError(`Assignments to a tag ${binding.type === 3 ? "parameter" : "variable"} must be within a script or function.`);
7088
+ 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.`);
6994
7089
  const fnRoot = getFnRoot(fnParent);
6995
7090
  const fnExtra = fnRoot && (fnRoot.node.extra ??= {});
6996
7091
  const section = getOrCreateSection(assignment);
@@ -7019,6 +7114,10 @@ function setReferencesScope(path) {
7019
7114
  const fnRoot = getFnRoot(path);
7020
7115
  if (fnRoot) (fnRoot.node.extra ??= {}).referencesScope = true;
7021
7116
  }
7117
+ const [getGlobalBinding] = createProgramState(() => createBinding("$global", 7, getOrCreateSection((0, _marko_compiler_babel_utils.getProgram)())));
7118
+ function trackGlobalReference(path) {
7119
+ trackReference(path, getGlobalBinding());
7120
+ }
7022
7121
  function createBindingsAndTrackReferences(lVal, type, scope, section, upstreamAlias, property, excludeProperties, restOffset) {
7023
7122
  switch (lVal.type) {
7024
7123
  case "Identifier": {
@@ -7141,6 +7240,7 @@ function finalizeReferences() {
7141
7240
  const exprBindings = resolveReferencedBindings(expr, reads, intersectionsBySection);
7142
7241
  expr.referencedBindings = exprBindings.referencedBindings;
7143
7242
  expr.lazyBindings = exprBindings.lazyBindings;
7243
+ expr.globalBindings = exprBindings.globalBindings;
7144
7244
  if (!exprBindings.referencedBindings) addSetupStatement(expr.section);
7145
7245
  forEach(exprBindings.lazyBindings, (binding) => {
7146
7246
  binding.forcePersist = true;
@@ -7156,7 +7256,9 @@ function finalizeReferences() {
7156
7256
  forEach(exprBindings.lazyBindings, (binding) => {
7157
7257
  addSerializeReason(binding.section, true, binding);
7158
7258
  });
7159
- }
7259
+ } else forEach(reads, (read) => {
7260
+ if (read.serializedValue) addSerializeExpr(read.binding.section, expr, read.binding);
7261
+ });
7160
7262
  if (exprBindings.allBindings) {
7161
7263
  const exprFnReads = fnReadsByExpression.get(expr);
7162
7264
  if (exprFnReads) for (const [fn, fnReads] of exprFnReads) {
@@ -7186,6 +7288,10 @@ function finalizeReferences() {
7186
7288
  forEachSection(finalizeTagDownstreams);
7187
7289
  for (const binding of bindings) {
7188
7290
  const { name, section } = binding;
7291
+ if (binding.type === 7) {
7292
+ resolveBindingSources(binding);
7293
+ continue;
7294
+ }
7189
7295
  if (binding.type !== 0) {
7190
7296
  resolveBindingSources(binding);
7191
7297
  forEach(binding.assignmentSections, (assignedSection) => {
@@ -7220,7 +7326,8 @@ function finalizeReferences() {
7220
7326
  section.referencedClosures = bindingUtil.add(section.referencedClosures, canonicalUpstreamAlias);
7221
7327
  }
7222
7328
  setReadsOwner(section, canonicalUpstreamAlias.section);
7223
- addOwnerSerializeReason(section, canonicalUpstreamAlias.section, !!isEffect || canonicalUpstreamAlias.sources);
7329
+ if (isEffect) addOwnerSerializeReason(section, canonicalUpstreamAlias.section, true);
7330
+ addOwnerSerializeReason(section, canonicalUpstreamAlias.section, canonicalUpstreamAlias.sources);
7224
7331
  }
7225
7332
  }
7226
7333
  }
@@ -7232,7 +7339,8 @@ function finalizeReferences() {
7232
7339
  addOwnerSerializeReason(section, hoistedBinding.section, true);
7233
7340
  });
7234
7341
  if (section.parent && section.isBranch && section.sectionAccessor && section.upstreamExpression) {
7235
- addSerializeReason(section, !!(section.isHoistThrough || section.hoisted) || getSerializeSourcesForRef(getDirectClosures(section)), kBranchSerializeReason);
7342
+ if (section.isHoistThrough || section.hoisted) addSerializeReason(section, true, kBranchSerializeReason);
7343
+ addSerializeReason(section, getSerializeSourcesForRef(getDirectClosures(section)), kBranchSerializeReason);
7236
7344
  addSerializeExpr(section, section.upstreamExpression, kBranchSerializeReason);
7237
7345
  addSerializeExpr(section.parent, section.upstreamExpression, section.sectionAccessor.binding);
7238
7346
  }
@@ -7263,16 +7371,16 @@ function finalizeReferences() {
7263
7371
  forEach(section.referencedClosures, (closure) => {
7264
7372
  const sourceSection = closure.section;
7265
7373
  let currentSection = section;
7266
- let branchesReason;
7374
+ let branchesForced = false;
7375
+ let branchesSources;
7267
7376
  while (currentSection !== sourceSection) {
7268
7377
  const upstreamReason = currentSection.downstreamBinding ? getSectionRegisterReasons(currentSection) || void 0 : !currentSection.upstreamExpression || getSerializeSourcesForExpr(currentSection.upstreamExpression);
7269
- if (upstreamReason === true) {
7270
- branchesReason = true;
7271
- break;
7272
- }
7273
- branchesReason = mergeSerializeReasons(branchesReason, upstreamReason);
7378
+ if (upstreamReason === true) branchesForced = true;
7379
+ else if (upstreamReason) branchesSources = mergeSources(branchesSources, upstreamReason);
7274
7380
  currentSection = currentSection.parent;
7275
7381
  }
7382
+ const branchesReason = branchesForced || branchesSources;
7383
+ if (branchesForced) addSerializeReason(sourceSection, branchesSources, closure);
7276
7384
  addSerializeReason(sourceSection, branchesReason, closure);
7277
7385
  addSerializeReason(sourceSection, getSerializeReason(sourceSection, closure));
7278
7386
  if (isDynamicClosure(section, closure)) {
@@ -7423,6 +7531,9 @@ function resolveBindingSources(binding) {
7423
7531
  case 3:
7424
7532
  binding.sources = createSources(void 0, getCanonicalBinding(binding));
7425
7533
  return;
7534
+ case 7:
7535
+ binding.sources = globalSources;
7536
+ return;
7426
7537
  }
7427
7538
  const aliasRoot = getAliasRoot(binding);
7428
7539
  if (aliasRoot) {
@@ -7459,15 +7570,17 @@ function resolveDerivedSources(binding) {
7459
7570
  });
7460
7571
  }
7461
7572
  }
7462
- function createSources(state, param) {
7463
- if (!(state || param)) throw new Error("Cannot create a serialize reason that does not reference state or a param.");
7573
+ function createSources(state, param, global) {
7574
+ if (!(state || param || global)) throw new Error("Cannot create a serialize reason that does not reference state, a param, or $global.");
7464
7575
  return {
7465
7576
  state,
7466
- param
7577
+ param,
7578
+ global
7467
7579
  };
7468
7580
  }
7469
7581
  function compareSources(a, b) {
7470
7582
  let delta;
7583
+ if (a.global !== b.global) return a.global ? 1 : -1;
7471
7584
  if (a.param) {
7472
7585
  if (!b.param) return 1;
7473
7586
  if (delta = compareReferences(a.param, b.param)) return delta;
@@ -7481,8 +7594,8 @@ function compareSources(a, b) {
7481
7594
  function mergeSources(a, b) {
7482
7595
  if (!a) return b;
7483
7596
  if (!b) return a;
7484
- if (a.state === b.state && a.param === b.param) return a;
7485
- return createSources(bindingUtil.union(a.state, b.state), unionParamSources(a.param, b.param));
7597
+ if (a.state === b.state && a.param === b.param && a.global === b.global) return a;
7598
+ return createSources(bindingUtil.union(a.state, b.state), unionParamSources(a.param, b.param), a.global || b.global);
7486
7599
  }
7487
7600
  function unionParamSources(a, b) {
7488
7601
  const merged = bindingUtil.union(a, b);
@@ -7542,6 +7655,14 @@ function dropExtra(exprExtra) {
7542
7655
  });
7543
7656
  }
7544
7657
  }
7658
+ function isSerializedChangeHandlerRead(exprRoot) {
7659
+ const markoRoot = getMarkoRoot(exprRoot);
7660
+ if (!markoRoot?.isMarkoAttribute()) return false;
7661
+ const attr = markoRoot.node;
7662
+ if (!isEventOrChangeHandler(attr.name) || isEventHandler(attr.name) || _marko_compiler.types.isFunction(attr.value)) return false;
7663
+ const tag = markoRoot.parentPath;
7664
+ return tag.isMarkoTag() && (tag.node.name.type !== "StringLiteral" || (0, _marko_compiler_babel_utils.isNativeTag)(tag));
7665
+ }
7545
7666
  function addReadToExpression(root, binding, getter) {
7546
7667
  const { node } = root;
7547
7668
  const fnRoot = getFnRoot(root);
@@ -7549,6 +7670,7 @@ function addReadToExpression(root, binding, getter) {
7549
7670
  const section = getOrCreateSection(exprRoot);
7550
7671
  const exprExtra = getCanonicalExtra(exprRoot.node.extra ??= { section });
7551
7672
  const read = addRead(exprExtra, node.extra ??= {}, binding, section, getter);
7673
+ if (!fnRoot && isSerializedChangeHandlerRead(exprRoot)) read.serializedValue = true;
7552
7674
  const { parent } = root;
7553
7675
  if (parent.type === "BinaryExpression" && (parent.operator === "===" || parent.operator === "!==")) read.comparedTo = parent.left === node ? parent.right : parent.left;
7554
7676
  if (!getter && binding.type === 5) {
@@ -7755,13 +7877,13 @@ function resolveReferencedBindingsInFunction(refs, reads) {
7755
7877
  const { getter, binding } = read;
7756
7878
  if (getter) {} else if (binding.type === 6) {
7757
7879
  if (bindingUtil.find(refs, binding)) constantBindings = bindingUtil.add(constantBindings, binding);
7758
- } else if (binding.type !== 0) referencedBindings = bindingUtil.add(referencedBindings, findClosestReference(read.binding, refs));
7880
+ } else if (binding.type !== 0 && binding.type !== 7) referencedBindings = bindingUtil.add(referencedBindings, findClosestReference(read.binding, refs));
7759
7881
  }
7760
7882
  else {
7761
7883
  const { getter, binding } = reads;
7762
7884
  if (getter) {} else if (binding.type === 6) {
7763
7885
  if (bindingUtil.find(refs, binding)) constantBindings = binding;
7764
- } else if (binding.type !== 0) referencedBindings = findClosestReference(binding, refs);
7886
+ } else if (binding.type !== 0 && binding.type !== 7) referencedBindings = findClosestReference(binding, refs);
7765
7887
  }
7766
7888
  return {
7767
7889
  referencedBindings,
@@ -7820,6 +7942,7 @@ function resolveReferencedBindings(expr, reads, intersectionsBySection) {
7820
7942
  let hoistedBindings;
7821
7943
  let allBindings;
7822
7944
  let lazyBindings;
7945
+ let globalBindings;
7823
7946
  if (Array.isArray(reads)) {
7824
7947
  const rootBindings = getRootBindings(reads);
7825
7948
  for (const read of reads) {
@@ -7838,11 +7961,12 @@ function resolveReferencedBindings(expr, reads, intersectionsBySection) {
7838
7961
  if (isChangeHandlerRead) {
7839
7962
  const upstreamRoot = binding.upstreamAlias && findClosestReference(binding.upstreamAlias, rootBindings);
7840
7963
  if (upstreamRoot) binding = upstreamRoot;
7841
- } else {
7964
+ } else if (binding.type !== 7) {
7842
7965
  extra.section = expr.section;
7843
7966
  ({binding} = extra.read ??= resolveExpressionReference(rootBindings, binding));
7844
7967
  }
7845
- if (isLazyRead(expr, read, binding, isChangeHandlerRead)) lazyBindings = bindingUtil.add(lazyBindings, binding);
7968
+ if (binding.type === 7) globalBindings = bindingUtil.add(globalBindings, binding);
7969
+ else if (isLazyRead(expr, read, binding, isChangeHandlerRead)) lazyBindings = bindingUtil.add(lazyBindings, binding);
7846
7970
  else if (binding.type === 6) constantBindings = bindingUtil.add(constantBindings, binding);
7847
7971
  else if (binding.type !== 0) referencedBindings = bindingUtil.add(referencedBindings, binding);
7848
7972
  }
@@ -7857,7 +7981,8 @@ function resolveReferencedBindings(expr, reads, intersectionsBySection) {
7857
7981
  binding.hoists = sectionUtil.add(binding.hoists, getter.hoisted);
7858
7982
  hoistedBindings = bindingUtil.add(hoistedBindings, binding);
7859
7983
  }
7860
- } else {
7984
+ } else if (binding.type === 7) globalBindings = binding;
7985
+ else {
7861
7986
  extra.read = createRead(binding, void 0, ownVar);
7862
7987
  if (isLazyRead(expr, reads, binding, extra.assignmentTo === binding)) lazyBindings = binding;
7863
7988
  else if (binding.type === 6) constantBindings = binding;
@@ -7889,7 +8014,8 @@ function resolveReferencedBindings(expr, reads, intersectionsBySection) {
7889
8014
  constantBindings,
7890
8015
  hoistedBindings,
7891
8016
  allBindings,
7892
- lazyBindings
8017
+ lazyBindings,
8018
+ globalBindings
7893
8019
  };
7894
8020
  }
7895
8021
  function resolveExpressionReference(rootBindings, readBinding) {
@@ -8129,27 +8255,34 @@ var class_default = {
8129
8255
  }
8130
8256
  };
8131
8257
  //#endregion
8258
+ //#region src/translator/util/statement-tag.ts
8259
+ function createStatementTag(keyword) {
8260
+ const target = keyword === "static" ? void 0 : keyword;
8261
+ const keywordReg = new RegExp(`^${keyword}\\s*`);
8262
+ return {
8263
+ parse(tag) {
8264
+ const { node, hub: { file } } = tag;
8265
+ const rawValue = node.rawValue;
8266
+ const code = rawValue.replace(keywordReg, "");
8267
+ const start = node.start + (rawValue.length - code.length);
8268
+ let body = (0, _marko_compiler_babel_utils.parseStatements)(file, code, start, start + code.length);
8269
+ if (body.length === 1 && _marko_compiler.types.isBlockStatement(body[0])) body = body[0].body;
8270
+ tag.replaceWith(_marko_compiler.types.markoScriptlet(body, true, target));
8271
+ },
8272
+ parseOptions: {
8273
+ statement: true,
8274
+ rawOpenTag: true
8275
+ },
8276
+ autocomplete: [{
8277
+ displayText: `${keyword} <statement>`,
8278
+ description: `A JavaScript statement which is only evaluated once your template is loaded${target ? ` on the ${target}` : ""}.`,
8279
+ descriptionMoreURL: `https://markojs.com/docs/reference/language#${keyword === "static" ? "static" : "server-and-client"}`
8280
+ }]
8281
+ };
8282
+ }
8283
+ //#endregion
8132
8284
  //#region src/translator/core/client.ts
8133
- var client_default = {
8134
- parse(tag) {
8135
- const { node, hub: { file } } = tag;
8136
- const rawValue = node.rawValue;
8137
- const code = rawValue.replace(/^client\s*/, "");
8138
- const start = node.start + (rawValue.length - code.length);
8139
- let body = (0, _marko_compiler_babel_utils.parseStatements)(file, code, start, start + code.length);
8140
- if (body.length === 1 && _marko_compiler.types.isBlockStatement(body[0])) body = body[0].body;
8141
- tag.replaceWith(_marko_compiler.types.markoScriptlet(body, true, "client"));
8142
- },
8143
- parseOptions: {
8144
- statement: true,
8145
- rawOpenTag: true
8146
- },
8147
- autocomplete: [{
8148
- displayText: "client <statement>",
8149
- description: "A JavaScript statement which is only evaluated once your template is loaded on the client.",
8150
- descriptionMoreURL: "https://markojs.com/docs/syntax/#client-javascript"
8151
- }]
8152
- };
8285
+ var client_default = createStatementTag("client");
8153
8286
  //#endregion
8154
8287
  //#region src/translator/core/const.ts
8155
8288
  var const_default = {
@@ -8396,7 +8529,8 @@ var html_comment_default = {
8396
8529
  const tagExtra = mergeReferences(tagSection, tag.node, referenceNodes);
8397
8530
  nodeBinding = tagExtra[kNodeBinding$1] = createBinding("#comment", 0, tagSection, void 0, void 0, void 0, void 0, !!tagVar);
8398
8531
  trackDomVarReferences(tag, nodeBinding);
8399
- addSerializeExpr(tagSection, !!tagVar || tagExtra, nodeBinding);
8532
+ if (tagVar) addSerializeExpr(tagSection, true, nodeBinding);
8533
+ addSerializeExpr(tagSection, tagExtra, nodeBinding);
8400
8534
  }
8401
8535
  const write = writeTo(tag);
8402
8536
  if (nodeBinding) visit(tag, 32);
@@ -8529,7 +8663,7 @@ var import_default = {
8529
8663
  parse(tag) {
8530
8664
  const { node } = tag;
8531
8665
  const statements = (0, _marko_compiler_babel_utils.parseStatements)(tag.hub.file, node.rawValue, node.start, node.end);
8532
- 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.");
8666
+ 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.");
8533
8667
  tag.replaceWith(statements[0]);
8534
8668
  },
8535
8669
  parseOptions: {
@@ -8540,7 +8674,7 @@ var import_default = {
8540
8674
  displayText: "import <scope> from \"<path>\"",
8541
8675
  description: "Use to import external modules, follows the same syntax as JavaScript imports.",
8542
8676
  snippet: "import ${2} from \"${1:path}\"",
8543
- descriptionMoreURL: "https://markojs.com/docs/syntax/#importing-external-files"
8677
+ descriptionMoreURL: "https://markojs.com/docs/reference/language#import"
8544
8678
  }]
8545
8679
  };
8546
8680
  //#endregion
@@ -8732,6 +8866,7 @@ var script_default = {
8732
8866
  const section = getSection(tag);
8733
8867
  const { value } = valueAttr;
8734
8868
  const referencedBindings = value.extra?.referencedBindings;
8869
+ 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." });
8735
8870
  if (isOutputDOM()) {
8736
8871
  const isFunction = _marko_compiler.types.isFunctionExpression(value) || _marko_compiler.types.isArrowFunctionExpression(value);
8737
8872
  let inlineBody = null;
@@ -8772,6 +8907,18 @@ function isAwaitExpression(node) {
8772
8907
  default: return false;
8773
8908
  }
8774
8909
  }
8910
+ function isReturnedFunction(node) {
8911
+ switch (node.type) {
8912
+ case "FunctionDeclaration":
8913
+ case "FunctionExpression":
8914
+ case "ArrowFunctionExpression":
8915
+ case "ClassMethod":
8916
+ case "ObjectMethod":
8917
+ case "ClassPrivateMethod": return skip;
8918
+ case "ReturnStatement": return _marko_compiler.types.isFunctionExpression(node.argument) || _marko_compiler.types.isArrowFunctionExpression(node.argument);
8919
+ default: return false;
8920
+ }
8921
+ }
8775
8922
  function isReturnStatement(node) {
8776
8923
  switch (node.type) {
8777
8924
  case "FunctionDeclaration":
@@ -8786,26 +8933,7 @@ function isReturnStatement(node) {
8786
8933
  }
8787
8934
  //#endregion
8788
8935
  //#region src/translator/core/server.ts
8789
- var server_default = {
8790
- parse(tag) {
8791
- const { node, hub: { file } } = tag;
8792
- const rawValue = node.rawValue;
8793
- const code = rawValue.replace(/^server\s*/, "");
8794
- const start = node.start + (rawValue.length - code.length);
8795
- let body = (0, _marko_compiler_babel_utils.parseStatements)(file, code, start, start + code.length);
8796
- if (body.length === 1 && _marko_compiler.types.isBlockStatement(body[0])) body = body[0].body;
8797
- tag.replaceWith(_marko_compiler.types.markoScriptlet(body, true, "server"));
8798
- },
8799
- parseOptions: {
8800
- statement: true,
8801
- rawOpenTag: true
8802
- },
8803
- autocomplete: [{
8804
- displayText: "server <statement>",
8805
- description: "A JavaScript statement which is only evaluated once your template is loaded on the server.",
8806
- descriptionMoreURL: "https://markojs.com/docs/syntax/#server-javascript"
8807
- }]
8808
- };
8936
+ var server_default = createStatementTag("server");
8809
8937
  //#endregion
8810
8938
  //#region src/translator/util/insertion-context.ts
8811
8939
  const discardsUnknownChildren = /* @__PURE__ */ new Set([
@@ -8944,7 +9072,8 @@ var show_default = {
8944
9072
  snippet: "show=${1:condition}",
8945
9073
  description: "Use to render content that is always mounted but only displayed when the condition is met.",
8946
9074
  descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#show"
8947
- }]
9075
+ }],
9076
+ types: runtime_info_default.name + "/tags/show.d.marko"
8948
9077
  };
8949
9078
  function isSingleNodeBody(tag) {
8950
9079
  let elements = 0;
@@ -8974,31 +9103,12 @@ function assertHasBody(tag) {
8974
9103
  function assertHasValueAttribute(tag) {
8975
9104
  const { node } = tag;
8976
9105
  const [valueAttr] = node.attributes;
8977
- 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).`);
9106
+ 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).`);
8978
9107
  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).`);
8979
9108
  }
8980
9109
  //#endregion
8981
9110
  //#region src/translator/core/static.ts
8982
- var static_default = {
8983
- parse(tag) {
8984
- const { node, hub: { file } } = tag;
8985
- const rawValue = node.rawValue;
8986
- const code = rawValue.replace(/^static\s*/, "");
8987
- const start = node.start + (rawValue.length - code.length);
8988
- let body = (0, _marko_compiler_babel_utils.parseStatements)(file, code, start, start + code.length);
8989
- if (body.length === 1 && _marko_compiler.types.isBlockStatement(body[0])) body = body[0].body;
8990
- tag.replaceWith(_marko_compiler.types.markoScriptlet(body, true));
8991
- },
8992
- parseOptions: {
8993
- statement: true,
8994
- rawOpenTag: true
8995
- },
8996
- autocomplete: [{
8997
- displayText: "static <statement>",
8998
- description: "A JavaScript statement which is only evaluated once your template is loaded.",
8999
- descriptionMoreURL: "https://markojs.com/docs/syntax/#static-javascript"
9000
- }]
9001
- };
9111
+ var static_default = createStatementTag("static");
9002
9112
  function checkStyleInterpolations(tag) {
9003
9113
  const { body } = tag.node.body;
9004
9114
  let stringQuote = "";
@@ -9148,7 +9258,7 @@ function checkDynamicStylePlacement(tag) {
9148
9258
  for (const sibling of tag.getAllPrevSiblings()) {
9149
9259
  if (isCoreTagName(sibling, "style")) continue;
9150
9260
  if (sibling.isMarkoText() ? /\S/.test(sibling.node.value) : getNodeContentType(sibling, "startType") !== null) {
9151
- (0, _marko_compiler_babel_utils.diagnosticWarn)(tag, { label: "The `${...}` values of a [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) only apply to elements rendered after it, so the content before this tag will not receive them. Move the `<style>` tag above the content it styles." });
9261
+ (0, _marko_compiler_babel_utils.diagnosticWarn)(tag, { label: "The `${...}` values of a [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) only apply to the subsequent siblings of the `<style>` tag and their descendants, so the content before this tag will not receive them. Move the `<style>` tag above the content it styles." });
9152
9262
  return;
9153
9263
  }
9154
9264
  }
@@ -9180,10 +9290,10 @@ function translateDOM$1(tag) {
9180
9290
  const { names, binding } = dynamic;
9181
9291
  const section = getSection(tag);
9182
9292
  const readEl = () => createScopeReadExpression(binding);
9183
- addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(callRuntime("_style_shell", scopeIdentifier, getScopeAccessorLiteral(binding))), void 0, true);
9293
+ addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(callRuntime("_style_shell", scopeIdentifier, getScopeAccessorLiteral(binding))), true);
9184
9294
  dynamicStyleValues(node).forEach((value, i) => {
9185
9295
  const valueRef = value.extra?.referencedBindings;
9186
- addStatement("render", section, valueRef, _marko_compiler.types.expressionStatement(callRuntime("_style_rule_item", readEl(), _marko_compiler.types.stringLiteral(names[i]), value)), void 0, !valueRef);
9296
+ addStatement("render", section, valueRef, _marko_compiler.types.expressionStatement(callRuntime("_style_rule_item", readEl(), _marko_compiler.types.stringLiteral(names[i]), value)), !valueRef);
9187
9297
  });
9188
9298
  }
9189
9299
  emitStyleImport(tag);
@@ -9276,7 +9386,13 @@ var try_default = {
9276
9386
  (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
9277
9387
  (0, _marko_compiler_babel_utils.assertNoParams)(tag);
9278
9388
  (0, _marko_compiler_babel_utils.assertNoAttributes)(tag);
9279
- analyzeAttributeTags(tag);
9389
+ const attrTags = analyzeAttributeTags(tag);
9390
+ if (attrTags) {
9391
+ for (const name in attrTags) if (name !== "@placeholder" && name !== "@catch") {
9392
+ const suggestion = name[1] === "p" ? "`<@placeholder>`" : "`<@catch>`";
9393
+ 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}?`);
9394
+ }
9395
+ }
9280
9396
  const section = getOrCreateSection(tag);
9281
9397
  const tagExtra = mergeReferences(section, tag.node, getAllTagReferenceNodes(tag.node));
9282
9398
  tagExtra[kDOMBinding$1] = createBinding("#text", 0, section);
@@ -9400,9 +9516,23 @@ var declaration_default = { translate: { enter(decl) {
9400
9516
  //#endregion
9401
9517
  //#region src/translator/visitors/document-type.ts
9402
9518
  var document_type_default = { translate: { exit(documentType) {
9403
- if (isOutputHTML()) writeTo$1(documentType)`<!${documentType.node.value}>`;
9519
+ if (isOutputHTML()) {
9520
+ writeTo$1(documentType)`<!${documentType.node.value}>`;
9521
+ if (getMarkoOpts().linkAssets && !isBeforeHtmlOrHead(documentType)) writeTo$1(documentType)`${callRuntime("_flush_head")}`;
9522
+ }
9404
9523
  documentType.remove();
9405
9524
  } } };
9525
+ function isBeforeHtmlOrHead(documentType) {
9526
+ let next = documentType.getNextSibling();
9527
+ while (next.node) {
9528
+ if (next.isMarkoTag()) {
9529
+ const { name } = next.node;
9530
+ return name.type === "StringLiteral" && (name.value === "html" || name.value === "head");
9531
+ }
9532
+ next = next.getNextSibling();
9533
+ }
9534
+ return false;
9535
+ }
9406
9536
  //#endregion
9407
9537
  //#region src/translator/visitors/import-declaration.ts
9408
9538
  const triggerRegExp = /\s*([\w-]+)\s*([^?|]+?)?\s*(?:\?([^|]*?))?\s*(?:\||$)/g;
@@ -9422,16 +9552,17 @@ var import_declaration_default = {
9422
9552
  }
9423
9553
  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;
9424
9554
  if (loadAttrPath) {
9555
+ const loadImport = getLoadImportConfig(loadAttrPath.get("value"));
9556
+ if ((node.importKind || "value") !== "value") throw importDecl.buildCodeFrameError("Invalid load import.");
9557
+ 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.");
9558
+ if (!node.specifiers.some(_marko_compiler.types.isImportDefaultSpecifier)) throw importDecl.buildCodeFrameError("Invalid load import, a default specifier is required.");
9425
9559
  if (!getMarkoOpts().linkAssets) {
9426
9560
  loadAttrPath.remove();
9427
9561
  return;
9428
9562
  }
9429
- (node.extra ??= {}).loadImport = getLoadImportConfig(loadAttrPath.get("value"));
9563
+ (node.extra ??= {}).loadImport = loadImport;
9430
9564
  const { file } = importDecl.hub;
9431
9565
  if (!(tagImport && (0, _marko_compiler_babel_utils.loadFileForImport)(file, value))) throw importDecl.buildCodeFrameError("Unable to resolve marko file for load import.");
9432
- if ((node.importKind || "value") !== "value") throw importDecl.buildCodeFrameError("Invalid load import.");
9433
- 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.");
9434
- if (!node.specifiers.some(_marko_compiler.types.isImportDefaultSpecifier)) throw importDecl.buildCodeFrameError("Invalid load import, a default specifier is required.");
9435
9566
  }
9436
9567
  },
9437
9568
  translate: { exit(importDecl) {
@@ -9449,6 +9580,7 @@ var import_declaration_default = {
9449
9580
  const wrappedName = getOrCreateHtmlLoadWrapped(getReadyId(loadFile), _marko_compiler.types.identifier(local.name), loadFile.opts.filename, loadImport.render ? void 0 : loadImport.triggers);
9450
9581
  for (const ref of binding.referencePaths) ref.replaceWith(_marko_compiler.types.identifier(wrappedName));
9451
9582
  node.source.value = tagImport;
9583
+ node.attributes = void 0;
9452
9584
  return;
9453
9585
  } else if (binding.referencePaths.every((ref) => _marko_compiler.types.isMarkoTag(ref.parent) && ref.parent.extra?.tagNameLoad)) importDecl.remove();
9454
9586
  else {
@@ -9554,7 +9686,7 @@ function isStaticText(node) {
9554
9686
  case "MarkoPlaceholder":
9555
9687
  if (node.escape) {
9556
9688
  const { confident, computed } = evaluate(node.value);
9557
- return confident && isNotVoid(computed);
9689
+ return confident && getHTMLRuntime()._escape(computed) !== "";
9558
9690
  }
9559
9691
  return false;
9560
9692
  }
@@ -9566,7 +9698,7 @@ function getPrevStaticSibling(path) {
9566
9698
  }
9567
9699
  function isEmptyPlaceholder(placeholder) {
9568
9700
  const { confident, computed } = evaluate(placeholder.value);
9569
- return confident && isVoid(computed);
9701
+ return confident && getHTMLRuntime()[placeholder.escape ? "_escape" : "_unescaped"](computed) === "";
9570
9702
  }
9571
9703
  //#endregion
9572
9704
  //#region src/translator/visitors/placeholder.ts
@@ -9579,7 +9711,7 @@ var placeholder_default = {
9579
9711
  const { node } = placeholder;
9580
9712
  const valueExtra = evaluate(node.value);
9581
9713
  const { confident, computed } = valueExtra;
9582
- if (confident && isVoid(computed)) return;
9714
+ if (confident && getHTMLRuntime()[node.escape ? "_escape" : "_unescaped"](computed) === "") return;
9583
9715
  if (!isStaticText(node)) {
9584
9716
  const section = getOrCreateSection(placeholder);
9585
9717
  const nodeBinding = (node.extra ??= {})[kNodeBinding] = createBinding("#text", 0, section);
@@ -9592,9 +9724,10 @@ var placeholder_default = {
9592
9724
  if (isNonHTMLText(placeholder)) return;
9593
9725
  const { node } = placeholder;
9594
9726
  const { confident, computed } = evaluate(node.value);
9595
- if (confident && isVoid(computed)) return;
9727
+ const staticText = confident ? getHTMLRuntime()[node.escape ? "_escape" : "_unescaped"](computed) : void 0;
9728
+ if (staticText === "") return;
9596
9729
  const extra = node.extra || {};
9597
- if (confident && node.escape) writeTo(placeholder)`${getHTMLRuntime()._escape(computed)}`;
9730
+ if (confident && node.escape) writeTo(placeholder)`${staticText}`;
9598
9731
  else {
9599
9732
  const siblingText = extra[kSiblingText];
9600
9733
  if (siblingText === 1 || siblingText === 2) visit(placeholder, 37);
@@ -9617,7 +9750,7 @@ function translateExit(placeholder) {
9617
9750
  if (node.extra?.[kRawText]) injectTextCoercion(value);
9618
9751
  const valueExtra = evaluate(value);
9619
9752
  const { confident, computed } = valueExtra;
9620
- if (confident && isVoid(computed)) {
9753
+ if (confident && getHTMLRuntime()[node.escape ? "_escape" : "_unescaped"](computed) === "") {
9621
9754
  placeholder.remove();
9622
9755
  return;
9623
9756
  }
@@ -9640,7 +9773,7 @@ function translateExit(placeholder) {
9640
9773
  if (isHTML) {
9641
9774
  write`${method === "_escape" ? buildEscapedTextExpression(value) : callRuntime(method, value)}`;
9642
9775
  if (nodeBinding) markNode(placeholder, nodeBinding, markerSerializeReason);
9643
- } else addStatement("render", section, valueExtra.referencedBindings, _marko_compiler.types.expressionStatement(method === "_text" ? callRuntime("_text", createScopeReadExpression(nodeBinding), value) : callRuntime("_html", scopeIdentifier, value, getScopeAccessorLiteral(nodeBinding))), void 0, true);
9776
+ } else addStatement("render", section, valueExtra.referencedBindings, _marko_compiler.types.expressionStatement(method === "_text" ? callRuntime("_text", createScopeReadExpression(nodeBinding), value) : callRuntime("_html", scopeIdentifier, value, getScopeAccessorLiteral(nodeBinding))), true);
9644
9777
  }
9645
9778
  placeholder.remove();
9646
9779
  }
@@ -9735,8 +9868,10 @@ var referenced_identifier_default = {
9735
9868
  analyze(identifier) {
9736
9869
  const { name } = identifier.node;
9737
9870
  if (identifier.scope.hasBinding(name)) return;
9738
- if (name === "$global") setReferencesScope(identifier);
9739
- else if (name === "$signal") {
9871
+ if (name === "$global") {
9872
+ setReferencesScope(identifier);
9873
+ trackGlobalReference(identifier);
9874
+ } else if (name === "$signal") {
9740
9875
  const section = getOrCreateSection(identifier);
9741
9876
  section.hasAbortSignal = true;
9742
9877
  setReferencesScope(identifier);
@@ -9761,7 +9896,7 @@ var referenced_identifier_default = {
9761
9896
  const resetEmitted = getAbortResetEmitted(section);
9762
9897
  if (!resetEmitted.has(exprRoot)) {
9763
9898
  resetEmitted.add(exprRoot);
9764
- addStatement("render", section, exprRoot.node.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(importRuntime("$signalReset"), [scopeIdentifier, _marko_compiler.types.numericLiteral(exprId)])), false);
9899
+ addStatement("render", section, exprRoot.node.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(importRuntime("$signalReset"), [scopeIdentifier, _marko_compiler.types.numericLiteral(exprId)])));
9765
9900
  }
9766
9901
  identifier.replaceWith(_marko_compiler.types.callExpression(importRuntime("$signal"), [scopeIdentifier, _marko_compiler.types.numericLiteral(exprId)]));
9767
9902
  }
@@ -10050,7 +10185,8 @@ var dynamic_tag_default = {
10050
10185
  }
10051
10186
  const bodySection = startSection(tagBody);
10052
10187
  trackParamsReferences(tagBody, 3);
10053
- addSerializeExpr(tagSection, hasVar || tagExtra, nodeBinding);
10188
+ if (hasVar) addSerializeExpr(tagSection, true, nodeBinding);
10189
+ addSerializeExpr(tagSection, tagExtra, nodeBinding);
10054
10190
  if (!hasVar && !node.arguments && !node.attributes.length && !node.body.body.length) tagExtra[kDirectContent] = true;
10055
10191
  if (tagExtra.featureType !== "class" || (0, _marko_compiler_babel_utils.getTagTemplate)(tag)) {
10056
10192
  visit(tag, hasVar ? 49 : 37);