marko 6.4.3 → 6.4.5

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 (74) hide show
  1. package/cheatsheet.md +2 -2
  2. package/dist/common/constants/renderer-prop.d.ts +2 -0
  3. package/dist/common/constants/renderer-prop.debug.d.ts +2 -0
  4. package/dist/debug/dom/catch.feat.js +1 -1
  5. package/dist/debug/dom/catch.feat.mjs +1 -1
  6. package/dist/debug/dom/controllable-input.feat.js +1 -1
  7. package/dist/debug/dom/controllable-input.feat.mjs +1 -1
  8. package/dist/debug/dom/controllable-open.feat.js +1 -1
  9. package/dist/debug/dom/controllable-open.feat.mjs +1 -1
  10. package/dist/debug/dom/controllable-select.feat.js +1 -1
  11. package/dist/debug/dom/controllable-select.feat.mjs +1 -1
  12. package/dist/debug/dom/controllable-textarea.feat.js +1 -1
  13. package/dist/debug/dom/controllable-textarea.feat.mjs +1 -1
  14. package/dist/debug/dom/controllable.feat.js +1 -1
  15. package/dist/debug/dom/controllable.feat.mjs +1 -1
  16. package/dist/debug/dom/dynamic-tag-script.feat.js +1 -1
  17. package/dist/debug/dom/dynamic-tag-script.feat.mjs +1 -1
  18. package/dist/debug/dom/dynamic-tag-var.feat.js +5 -1
  19. package/dist/debug/dom/dynamic-tag-var.feat.mjs +5 -1
  20. package/dist/debug/dom/lazy.feat.js +1 -1
  21. package/dist/debug/dom/lazy.feat.mjs +1 -1
  22. package/dist/debug/dom/placeholder.feat.js +1 -1
  23. package/dist/debug/dom/placeholder.feat.mjs +1 -1
  24. package/dist/debug/{dom-uEY0J_H9.mjs → dom-BeY1nGUb.mjs} +15 -12
  25. package/dist/debug/{dom-C7F3yZTh.js → dom-CUxvM4i9.js} +32 -23
  26. package/dist/debug/dom.js +3 -10
  27. package/dist/debug/dom.mjs +3 -10
  28. package/dist/debug/html.js +30 -24
  29. package/dist/debug/html.mjs +30 -24
  30. package/dist/dom/catch.feat.js +4 -4
  31. package/dist/dom/catch.feat.mjs +1 -1
  32. package/dist/dom/control-flow.d.ts +2 -2
  33. package/dist/dom/controllable-input.feat.js +2 -2
  34. package/dist/dom/controllable-input.feat.mjs +1 -1
  35. package/dist/dom/controllable-open.feat.js +2 -2
  36. package/dist/dom/controllable-open.feat.mjs +1 -1
  37. package/dist/dom/controllable-select.feat.js +2 -2
  38. package/dist/dom/controllable-select.feat.mjs +1 -1
  39. package/dist/dom/controllable-textarea.feat.js +2 -2
  40. package/dist/dom/controllable-textarea.feat.mjs +1 -1
  41. package/dist/dom/controllable.feat.js +2 -2
  42. package/dist/dom/controllable.feat.mjs +1 -1
  43. package/dist/dom/dynamic-tag-script.feat.js +2 -2
  44. package/dist/dom/dynamic-tag-script.feat.mjs +1 -1
  45. package/dist/dom/dynamic-tag-var.feat.js +3 -3
  46. package/dist/dom/dynamic-tag-var.feat.mjs +1 -1
  47. package/dist/dom/lazy.feat.js +1 -1
  48. package/dist/dom/lazy.feat.mjs +1 -1
  49. package/dist/dom/load.d.ts +0 -1
  50. package/dist/dom/placeholder.feat.js +3 -3
  51. package/dist/dom/placeholder.feat.mjs +1 -1
  52. package/dist/dom/renderer.d.ts +9 -2
  53. package/dist/{dom-DHg9YChM.mjs → dom-DefWmvQB.mjs} +10 -7
  54. package/dist/{dom-CtIT8Mpr.js → dom-Diu8MpmL.js} +124 -126
  55. package/dist/dom.d.ts +2 -2
  56. package/dist/dom.js +31 -37
  57. package/dist/dom.mjs +2 -8
  58. package/dist/html/assets.d.ts +1 -1
  59. package/dist/html/content.d.ts +1 -0
  60. package/dist/html/dynamic-tag.d.ts +1 -1
  61. package/dist/html/template.d.ts +1 -0
  62. package/dist/html.js +12 -11
  63. package/dist/html.mjs +12 -11
  64. package/dist/translator/index.js +202 -109
  65. package/dist/translator/util/entry-builder.d.ts +10 -3
  66. package/dist/translator/util/module-registrations.d.ts +1 -1
  67. package/dist/translator/util/references.d.ts +2 -1
  68. package/dist/translator/util/signals.d.ts +10 -1
  69. package/dist/translator/util/solve-reasons.d.ts +1 -0
  70. package/dist/translator/util/write-guard.d.ts +4 -0
  71. package/dist/translator/visitors/function.d.ts +15 -10
  72. package/dist/translator/visitors/import-declaration.d.ts +3 -4
  73. package/package.json +4 -4
  74. package/tags-html.d.ts +3 -2
@@ -955,7 +955,7 @@ function createSectionState(key, init) {
955
955
  //#region src/translator/visitors/function.ts
956
956
  const kRegisteredExports = Symbol("registered exports");
957
957
  const [getReferencesByFn] = createProgramState(() => /* @__PURE__ */ new Map());
958
- const [getReferencesByImportedFn] = createProgramState(() => /* @__PURE__ */ new Map());
958
+ const [getReferencesByImport] = createProgramState(() => /* @__PURE__ */ new Map());
959
959
  var function_default = { analyze(fn) {
960
960
  const awaitNode = isMarkoAttribute(fn.parentPath) && _marko_compiler.types.isFunctionExpression(fn.node) && !fn.node.async && traverseFindAwait(fn.node.body);
961
961
  if (awaitNode) {
@@ -989,24 +989,45 @@ function resolveFunctionReason() {
989
989
  }
990
990
  function finalizeFunctionRegistry() {
991
991
  for (const fnExtra of getReferencesByFn().keys()) if (fnExtra.reason) registerFunction(fnExtra);
992
- for (const [importedFn, exprExtras] of getReferencesByImportedFn()) if (resolveReason(exprExtras)) registerImportedFn(importedFn);
992
+ for (const [{ node, local, registered, fnRoots }, exprExtras] of getReferencesByImport()) {
993
+ const reason = fnRoots ? resolveTemplateReason(exprExtras) : resolveReason(exprExtras);
994
+ if (reason) {
995
+ if (!fnRoots || !isTemplateShipped(fnRoots, exprExtras)) {
996
+ const extra = node.extra ??= {};
997
+ extra.registeredImports ??= /* @__PURE__ */ new Map();
998
+ extra.registeredImports.set(local, registered);
999
+ }
1000
+ markRegistrationInteractive(reason);
1001
+ }
1002
+ }
1003
+ }
1004
+ /**
1005
+ * Tracks a template imported as a default export. The server writes a template
1006
+ * only as a binding's value, so the importing template registers it when one may.
1007
+ */
1008
+ function trackImportedTemplate(importDecl, local, templateFile) {
1009
+ trackImport(importDecl, local, {
1010
+ registerId: templateFile.metadata.marko.id,
1011
+ exportName: "default",
1012
+ filename: templateFile.opts.filename
1013
+ }, /* @__PURE__ */ new Set());
993
1014
  }
994
1015
  /**
995
- * Tracks a function imported from another template that reserved a register id.
996
- * The importing template registers it (under the reserved id) when client
1016
+ * Tracks an export imported from another template that registers under an id,
1017
+ * if it does. The importing template registers it (under that id) when client
997
1018
  * code reads its own references.
998
1019
  */
999
- function trackImportedFn(importDecl, local, resolved) {
1000
- const binding = importDecl.scope.getBinding(local);
1020
+ function trackImport(importDecl, local, registered, fnRoots) {
1021
+ const binding = registered && importDecl.scope.getBinding(local);
1001
1022
  if (!binding) return;
1002
- const importedFn = {
1003
- ...resolved,
1004
- node: importDecl.node,
1005
- local
1006
- };
1007
1023
  const refs = /* @__PURE__ */ new Set();
1008
- addBindingRefs(binding, refs, /* @__PURE__ */ new Set());
1009
- if (refs.size) getReferencesByImportedFn().set(importedFn, refs);
1024
+ addBindingRefs(binding, refs, /* @__PURE__ */ new Set(), fnRoots);
1025
+ if (refs.size) getReferencesByImport().set({
1026
+ node: importDecl.node,
1027
+ local,
1028
+ registered,
1029
+ fnRoots
1030
+ }, refs);
1010
1031
  }
1011
1032
  /**
1012
1033
  * Finds the id reserved for an export, following `export ... from` hops. Each
@@ -1015,15 +1036,11 @@ function trackImportedFn(importDecl, local, resolved) {
1015
1036
  * hand out an incomplete map if the ids were pushed ahead of time.
1016
1037
  */
1017
1038
  function resolveRegisteredExport(file, exportName, seen = /* @__PURE__ */ new Set()) {
1018
- const filename = file.opts.filename;
1019
- const key = `${filename}\0${exportName}`;
1039
+ const key = `${file.opts.filename}\0${exportName}`;
1020
1040
  if (seen.has(key)) return;
1021
1041
  seen.add(key);
1022
- const reserved = file.ast.program.extra?.[kRegisteredExports]?.get(exportName);
1023
- if (reserved) return {
1024
- ...reserved,
1025
- filename
1026
- };
1042
+ const registered = file.ast.program.extra?.[kRegisteredExports]?.get(exportName);
1043
+ if (registered) return registered;
1027
1044
  for (const child of file.ast.program.body) {
1028
1045
  if (child.type !== "ExportNamedDeclaration" && child.type !== "ExportAllDeclaration" || !child.source || (child.exportKind || "value") !== "value") continue;
1029
1046
  const sourceFile = (0, _marko_compiler_babel_utils.loadFileForImport)(file, child.source.value);
@@ -1048,11 +1065,21 @@ function resolveReason(exprExtras) {
1048
1065
  }
1049
1066
  return reason;
1050
1067
  }
1051
- function registerImportedFn({ node, ...importedFn }) {
1052
- const extra = node.extra ??= {};
1053
- extra.registeredImportedFns ??= [];
1054
- extra.registeredImportedFns.push(importedFn);
1055
- (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
1068
+ function resolveTemplateReason(exprExtras) {
1069
+ let reason;
1070
+ for (const exprExtra of exprExtras) {
1071
+ const extra = getCanonicalExtra(exprExtra);
1072
+ if (!extra.isEffect) reason = mergeReasons(reason, getReasonForExpr(extra));
1073
+ }
1074
+ return reason;
1075
+ }
1076
+ function isTemplateShipped(fnRoots, exprExtras) {
1077
+ for (const fnRoot of fnRoots) if (isRegisteredFnExtra(fnRoot)) return true;
1078
+ for (const exprExtra of exprExtras) if (getCanonicalExtra(exprExtra).isEffect) return true;
1079
+ return false;
1080
+ }
1081
+ function markRegistrationInteractive(reason) {
1082
+ (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive ||= isUnconditionalReason(reason);
1056
1083
  }
1057
1084
  function reserveExportRegisterId(fnExtra, fn, markoRoot) {
1058
1085
  if (!isStatic(markoRoot)) return;
@@ -1062,12 +1089,14 @@ function reserveExportRegisterId(fnExtra, fn, markoRoot) {
1062
1089
  const { markoOpts, opts: { filename } } = (0, _marko_compiler_babel_utils.getFile)();
1063
1090
  const programExtra = (0, _marko_compiler_babel_utils.getProgram)().node.extra;
1064
1091
  const registerId = (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, filename, `${fnExtra.section.id}/export/${exportName}`);
1092
+ const registered = {
1093
+ registerId,
1094
+ exportName,
1095
+ filename
1096
+ };
1065
1097
  fnExtra.exportRegisterId = registerId;
1066
1098
  programExtra[kRegisteredExports] ??= /* @__PURE__ */ new Map();
1067
- for (const name of exportNames) programExtra[kRegisteredExports].set(name, {
1068
- registerId,
1069
- exportName
1070
- });
1099
+ for (const name of exportNames) programExtra[kRegisteredExports].set(name, registered);
1071
1100
  }
1072
1101
  function getExportNames(fn, markoRoot) {
1073
1102
  const localName = getExportableName(fn);
@@ -1095,31 +1124,35 @@ function getExportedName(specifier) {
1095
1124
  function canIgnoreRegister(markoRoot, exprRoot) {
1096
1125
  return markoRoot.isMarkoPlaceholder() || markoRoot.isMarkoScriptlet() && (!markoRoot.node.static || markoRoot.node.target === "server") || markoRoot.isMarkoTag() && markoRoot.node.name == exprRoot.node;
1097
1126
  }
1098
- function getStaticDeclRefs(path, refs = /* @__PURE__ */ new Set(), seen = /* @__PURE__ */ new Set()) {
1127
+ function getStaticDeclRefs(path, refs = /* @__PURE__ */ new Set(), seen = /* @__PURE__ */ new Set(), fnRoots) {
1099
1128
  const decl = getDeclarationRoot(path);
1100
1129
  if (decl && !seen.has(decl.node)) {
1101
1130
  seen.add(decl.node);
1102
1131
  const ids = decl.getOuterBindingIdentifiers();
1103
1132
  if (ids) for (const name in ids) {
1104
1133
  const binding = decl.scope.getBinding(name);
1105
- if (binding) addBindingRefs(binding, refs, seen);
1134
+ if (binding) addBindingRefs(binding, refs, seen, fnRoots);
1106
1135
  }
1107
1136
  }
1108
1137
  return refs;
1109
1138
  }
1110
- function addBindingRefs(binding, refs, seen) {
1139
+ function addBindingRefs(binding, refs, seen, fnRoots) {
1111
1140
  for (const ref of binding.referencePaths) {
1112
1141
  if (isInvokedFunction(ref) || ref.parentPath.type === "Program") continue;
1113
1142
  const exprRoot = getExprRoot(ref);
1114
1143
  const markoRoot = getMarkoRoot(exprRoot);
1115
1144
  if (!markoRoot || canIgnoreRegister(markoRoot, exprRoot)) continue;
1116
- if (isStatic(markoRoot)) getStaticDeclRefs(ref, refs, seen);
1145
+ if (fnRoots) {
1146
+ const fnRoot = getFnRoot(ref);
1147
+ if (fnRoot) fnRoots.add(fnRoot.node.extra ??= {});
1148
+ }
1149
+ if (isStatic(markoRoot)) getStaticDeclRefs(ref, refs, seen, fnRoots);
1117
1150
  else refs.add(exprRoot.node.extra ??= {});
1118
1151
  }
1119
1152
  }
1120
1153
  function registerFunction(fnExtra) {
1121
- const { markoOpts, path: program, opts: { filename } } = (0, _marko_compiler_babel_utils.getFile)();
1122
- program.node.extra.isInteractive = true;
1154
+ const { markoOpts, opts: { filename } } = (0, _marko_compiler_babel_utils.getFile)();
1155
+ markRegistrationInteractive(fnExtra.reason);
1123
1156
  fnExtra.name = generateUid(fnExtra.name);
1124
1157
  fnExtra.registerId = fnExtra.exportRegisterId ?? (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, filename, `${fnExtra.section.id}/${fnExtra.name.slice(1)}`);
1125
1158
  }
@@ -1593,7 +1626,7 @@ function _escape(val) {
1593
1626
  return val ? escapeXMLStr(val + "") : val === 0 ? "0" : "";
1594
1627
  }
1595
1628
  const unsafeScriptReg = /<(\/?script|!--)/gi;
1596
- const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str;
1629
+ const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\u003C$1") : str;
1597
1630
  function _escape_script(val) {
1598
1631
  return val ? escapeScriptStr(val + "") : val === 0 ? "0" : "";
1599
1632
  }
@@ -1662,6 +1695,7 @@ const pureDOMFunctions = /* @__PURE__ */ new Set([
1662
1695
  "_dynamic_tag_content",
1663
1696
  "_content_closures",
1664
1697
  "_template",
1698
+ "_return_setup",
1665
1699
  "_closure",
1666
1700
  "_closure_get",
1667
1701
  "_or",
@@ -1680,7 +1714,6 @@ const pureDOMFunctions = /* @__PURE__ */ new Set([
1680
1714
  "_const",
1681
1715
  "_load_signal",
1682
1716
  "_load_setup",
1683
- "_load_setup_var",
1684
1717
  "_load_template",
1685
1718
  "_load_visible_trigger",
1686
1719
  "_load_event_trigger",
@@ -1801,12 +1834,12 @@ const builder = {
1801
1834
  }
1802
1835
  return body;
1803
1836
  },
1804
- visit(file, entryFile, visitChild = (id, bundled = false) => {
1837
+ visit(file, entryFile, visitChild = (id, reach = 0) => {
1805
1838
  const state = entryFile[kState];
1806
1839
  const resolved = resolveRelativeToEntry(entryFile, file, id);
1807
- const seenBundled = state.visited.get(resolved);
1808
- if (seenBundled === false || seenBundled && bundled) return;
1809
- state.visited.set(resolved, bundled);
1840
+ const seen = state.visited.get(resolved);
1841
+ if (seen !== void 0 && seen <= reach) return;
1842
+ state.visited.set(resolved, reach);
1810
1843
  const childFile = (0, _marko_compiler_babel_utils.loadFileForImport)(entryFile, resolved);
1811
1844
  if (childFile) builder.visit(childFile, entryFile);
1812
1845
  }) {
@@ -1815,10 +1848,11 @@ const builder = {
1815
1848
  load: false,
1816
1849
  lazy: false,
1817
1850
  bundled: 0,
1851
+ lazyDepth: 0,
1818
1852
  roots: [],
1819
1853
  assets: /* @__PURE__ */ new Set(),
1820
1854
  bundledAssets: /* @__PURE__ */ new Set(),
1821
- visited: /* @__PURE__ */ new Map([[(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, entryFile.opts.filename), false]])
1855
+ visited: /* @__PURE__ */ new Map([[(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, entryFile.opts.filename), 0]])
1822
1856
  };
1823
1857
  const programExtra = file.path.node.extra;
1824
1858
  const { analyzedTags, assetImports } = file.metadata.marko;
@@ -1830,16 +1864,22 @@ const builder = {
1830
1864
  if (load) state.load = true;
1831
1865
  if (loadImports) state.lazy = true;
1832
1866
  if (isRoot) state.roots.push((0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, file.opts.filename));
1833
- if (assetImports) {
1867
+ if (assetImports && !state.lazyDepth) {
1834
1868
  const assets = isRoot || state.bundled ? state.bundledAssets : state.assets;
1835
1869
  for (const request of assetImports) assets.add(resolveRelativeToEntry(entryFile, file, request));
1836
1870
  }
1837
1871
  if (isRoot) state.bundled++;
1838
1872
  for (const tag of analyzedTags ? [...analyzedTags] : []) {
1839
1873
  const lazy = loadImports?.has(tag);
1840
- if (lazy) state.bundled++;
1841
- visitChild(tag, !!state.bundled);
1842
- if (lazy) state.bundled--;
1874
+ if (lazy) {
1875
+ state.bundled++;
1876
+ state.lazyDepth++;
1877
+ }
1878
+ visitChild(tag, state.lazyDepth ? 2 : state.bundled ? 1 : 0);
1879
+ if (lazy) {
1880
+ state.bundled--;
1881
+ state.lazyDepth--;
1882
+ }
1843
1883
  }
1844
1884
  if (isRoot) state.bundled--;
1845
1885
  }
@@ -1890,19 +1930,20 @@ function escapeRegExp(str) {
1890
1930
  /**
1891
1931
  * Writes the registrations for module scoped functions: the ones this template
1892
1932
  * exports and registers itself, and the ones it imports from a template that
1893
- * reserved a register id without registering it.
1933
+ * reserved a register id without registering it; and for templates it imports.
1894
1934
  */
1895
1935
  function writeModuleRegistrations(program) {
1896
1936
  const file = (0, _marko_compiler_babel_utils.getFile)();
1897
1937
  const statements = [];
1898
1938
  const seen = /* @__PURE__ */ new Set();
1899
1939
  for (const child of program.node.body) {
1900
- const registeredImportedFns = _marko_compiler.types.isImportDeclaration(child) && child.extra?.registeredImportedFns;
1901
- if (registeredImportedFns) for (const importedFn of registeredImportedFns) {
1902
- if (seen.has(importedFn.registerId)) continue;
1903
- seen.add(importedFn.registerId);
1904
- if (isOutputHTML()) statements.push(buildRegistration(importedFn.local, importedFn.registerId));
1905
- else (0, _marko_compiler_babel_utils.importDefault)(file, resolveRegisterModule(file, importedFn));
1940
+ const registeredImports = _marko_compiler.types.isImportDeclaration(child) && child.extra?.registeredImports;
1941
+ if (registeredImports) for (const [local, registered] of registeredImports) {
1942
+ if (seen.has(registered.registerId)) continue;
1943
+ seen.add(registered.registerId);
1944
+ if (isOutputHTML()) {
1945
+ if (registered.exportName !== "default") statements.push(buildRegistration(local, registered.registerId));
1946
+ } else (0, _marko_compiler_babel_utils.importDefault)(file, resolveRegisterModule(file, registered));
1906
1947
  }
1907
1948
  else if (child.type === "ExportNamedDeclaration") addExportRegistrations(child, seen, statements);
1908
1949
  }
@@ -1933,7 +1974,7 @@ function resolveRegisterModule(file, { filename, exportName, registerId }) {
1933
1974
  const importer = file.opts.filename;
1934
1975
  return getMarkoOpts().resolveVirtualDependency(importer, {
1935
1976
  virtualPath: `${relativePath(importer, filename)}.register-${exportName}.js`,
1936
- code: `import { ${exportName} } from "./${path.default.basename(filename)}";\nimport { _resumed } from "${getRuntimePath("dom")}";\n_resumed${isValidPropertyIdentifier(registerId) ? `.${registerId}` : `[${JSON.stringify(registerId)}]`} = ${exportName};\n`
1977
+ code: `import { ${exportName} as value } from "./${path.default.basename(filename)}";\nimport { _resumed } from "${getRuntimePath("dom")}";\n_resumed${isValidPropertyIdentifier(registerId) ? `.${registerId}` : `[${JSON.stringify(registerId)}]`} = value;\n`
1937
1978
  });
1938
1979
  }
1939
1980
  function relativePath(from, to) {
@@ -2157,7 +2198,7 @@ var import_declaration_default = {
2157
2198
  if (tagImport) {
2158
2199
  const tags = (0, _marko_compiler_babel_utils.getFile)().metadata.marko.tags;
2159
2200
  if (!tags.includes(tagImport)) tags.push(tagImport);
2160
- trackImportedRegisteredFns(importDecl);
2201
+ trackRegisteredImports(importDecl);
2161
2202
  }
2162
2203
  const loadAttrPath = getLoadAttr(importDecl);
2163
2204
  if (loadAttrPath) {
@@ -2198,7 +2239,9 @@ var import_declaration_default = {
2198
2239
  } else if (binding.referencePaths.every((ref) => _marko_compiler.types.isMarkoTag(ref.parent) && ref.parent.extra?.tagNameLoad)) importDecl.remove();
2199
2240
  else {
2200
2241
  importRuntimeFeature("catch");
2201
- importDecl.replaceWith(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(local, callRuntime("_load_template", _marko_compiler.types.stringLiteral(loadFile.metadata.marko.id), _marko_compiler.types.arrowFunctionExpression([], dynamicImport((0, _marko_compiler_babel_utils.resolveRelativePath)(file, loadFile.opts.filename), _marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.identifier("mod")], toMemberExpression(_marko_compiler.types.identifier("mod"), "default"))))))]));
2242
+ const load = _marko_compiler.types.arrowFunctionExpression([], dynamicImport((0, _marko_compiler_babel_utils.resolveRelativePath)(file, loadFile.opts.filename), _marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.identifier("mod")], toMemberExpression(_marko_compiler.types.identifier("mod"), "default"))));
2243
+ const args = [_marko_compiler.types.stringLiteral(loadFile.metadata.marko.id), load];
2244
+ importDecl.replaceWith(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(local, extra.registeredImports?.has(local.name) ? _marko_compiler.types.callExpression(importRuntime("_load_template"), args) : callRuntime("_load_template", ...args))]));
2202
2245
  }
2203
2246
  return;
2204
2247
  }
@@ -2230,17 +2273,19 @@ function getOrCreateHtmlLoadWrapped(readyId, originalIdentifier, filename, trigg
2230
2273
  (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.markoScriptlet([_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(wrappedName), callRuntime("withLoadAssets", originalIdentifier, (0, _marko_compiler_babel_utils.importNamed)((0, _marko_compiler_babel_utils.getFile)(), markoOpts.linkAssets.runtime, "flush"), _marko_compiler.types.stringLiteral(readyId), triggers ? _marko_compiler.types.valueToNode(triggers) : void 0))])], true));
2231
2274
  return wrappedName;
2232
2275
  }
2233
- function trackImportedRegisteredFns(importDecl) {
2276
+ function trackRegisteredImports(importDecl) {
2234
2277
  const { node } = importDecl;
2235
2278
  const childFile = (0, _marko_compiler_babel_utils.loadFileForImport)((0, _marko_compiler_babel_utils.getFile)(), node.source.value);
2236
2279
  if (!childFile) return;
2237
2280
  for (const specifier of importDecl.get("specifiers")) {
2238
- if (!specifier.isImportSpecifier()) continue;
2239
- const { imported } = specifier.node;
2240
- const importedName = imported.type === "Identifier" ? imported.name : imported.value;
2241
- if (importedName === "default") continue;
2242
- const resolved = resolveRegisteredExport(childFile, importedName);
2243
- if (resolved) trackImportedFn(importDecl, specifier.node.local.name, resolved);
2281
+ let importedName = "default";
2282
+ if (specifier.isImportSpecifier()) {
2283
+ const { imported } = specifier.node;
2284
+ importedName = imported.type === "Identifier" ? imported.name : imported.value;
2285
+ } else if (!specifier.isImportDefaultSpecifier()) continue;
2286
+ const local = specifier.node.local.name;
2287
+ if (importedName === "default") trackImportedTemplate(importDecl, local, childFile);
2288
+ else trackImport(importDecl, local, resolveRegisteredExport(childFile, importedName));
2244
2289
  }
2245
2290
  }
2246
2291
  function getLoadAttr(importDecl) {
@@ -2720,6 +2765,12 @@ function buildGroupMask(groups) {
2720
2765
  function getScopeReasonStatement(section) {
2721
2766
  return hasConditionalReason(section) ? _marko_compiler.types.variableDeclaration("const", getSectionGuards(section).declarators) : _marko_compiler.types.expressionStatement(callRuntime("_scope_reason"));
2722
2767
  }
2768
+ function getWriteReason(binding) {
2769
+ return findSlot(binding)?.reason;
2770
+ }
2771
+ function getBranchWriteReason(section) {
2772
+ return findSectionSlot(section, 9)?.reason;
2773
+ }
2723
2774
  function getWriteGuard(section, reason, optional) {
2724
2775
  if (!isDynamicWriteGuard(section, reason)) {
2725
2776
  if (!reason) return _marko_compiler.types.numericLiteral(0);
@@ -3204,8 +3255,12 @@ function getDestructurePattern(id) {
3204
3255
  //#region src/translator/util/signals.ts
3205
3256
  const [getSignals] = createSectionState("signals", () => /* @__PURE__ */ new Map());
3206
3257
  const [getClosureSignalBuilder, _setClosureSignalBuilder] = createSectionState("queue");
3207
- function setClosureSignalBuilder(tag, builder) {
3208
- _setClosureSignalBuilder(getSectionForBody(tag.get("body")), builder);
3258
+ function setClosureSignalBuilder(tag, hop, build = (_closure, render) => buildClosureHop(hop, render)) {
3259
+ _setClosureSignalBuilder(getSectionForBody(tag.get("body")), build);
3260
+ }
3261
+ function buildClosureHop(hop, render) {
3262
+ const accessor = getScopeAccessorLiteral(hop.ref, true);
3263
+ return hop.kind === "if" ? callRuntime("_if_closure", accessor, _marko_compiler.types.numericLiteral(hop.index), render) : callRuntime("_for_closure", accessor, render);
3209
3264
  }
3210
3265
  const [getOwnerResumedByMarker, setOwnerResumedByMarker] = createSectionState("ownerResumedByMarker");
3211
3266
  function setSectionOwnerResumedByMarker(section) {
@@ -3666,7 +3721,10 @@ function writeHTMLResumeStatements(path) {
3666
3721
  const closureScopesReason = findSlot(closure, 2)?.reason;
3667
3722
  const subscribeArg = isConditionalReason(closureScopesReason) && !isSameReason(closureScopesReason, sectionReason) ? getExprIfWritten(closure.section, closureScopesReason, identifier) : identifier;
3668
3723
  const changeable = isChangeableDynamicClosure(section, closure);
3669
- addWriteScopeBuilder(section, (expr) => callRuntime("_subscribe", subscribeArg, expr, changeable ? _marko_compiler.types.stringLiteral(getResumeRegisterId(section, closure, "subscribe")) : void 0, changeable ? markerGuard : void 0));
3724
+ addWriteScopeBuilder(section, (expr) => {
3725
+ const resumeId = changeable && _marko_compiler.types.stringLiteral(getResumeRegisterId(section, closure, "subscribe"));
3726
+ return callRuntime("_subscribe", subscribeArg, expr, resumeId, resumeId && markerGuard);
3727
+ });
3670
3728
  }
3671
3729
  }
3672
3730
  });
@@ -3684,7 +3742,7 @@ function writeHTMLResumeStatements(path) {
3684
3742
  };
3685
3743
  let debugVars;
3686
3744
  const writeBinding = (binding) => {
3687
- const reason = findSlot(binding)?.reason;
3745
+ const reason = getWriteReason(binding);
3688
3746
  if (!reason) return;
3689
3747
  const accessor = getScopeAccessor(binding);
3690
3748
  pendingProperties.delete(accessor);
@@ -3715,7 +3773,8 @@ function writeHTMLResumeStatements(path) {
3715
3773
  for (const [accessor, varLoc] of getSectionDebugVars(section)) (debugVars ||= []).push(toObjectProperty(accessor, _marko_compiler.types.valueToNode(varLoc)));
3716
3774
  if (debugVars) writeScopeArgs.push(_marko_compiler.types.objectExpression(debugVars));
3717
3775
  }
3718
- body.push(_marko_compiler.types.expressionStatement(getExprIfWritten(section, sectionReason, writeScopeBuilder ? writeScopeBuilder(callRuntime("_scope", ...writeScopeArgs)) : callRuntime("_scope", ...writeScopeArgs))));
3776
+ const writeCall = writeScopeBuilder ? writeScopeBuilder(callRuntime("_scope", ...writeScopeArgs)) : callRuntime("_scope", ...writeScopeArgs);
3777
+ body.push(_marko_compiler.types.expressionStatement(getExprIfWritten(section, sectionReason, writeCall)));
3719
3778
  }
3720
3779
  if (!isResumedBranch(section) && (section.hasAbortSignal || !!section.referencedClosures || sectionReason && some(section.bindings, isLetBinding)) && markerGuard) {
3721
3780
  const call = callRuntime("_resume_branch", scopeIdIdentifier);
@@ -4299,8 +4358,7 @@ var dom_default = { translate: {
4299
4358
  let renderer = callRuntime("_content", _marko_compiler.types.stringLiteral(registerId), ...replaceNullishAndEmptyFunctionsWith0([
4300
4359
  writes,
4301
4360
  walks,
4302
- setupIdentifier,
4303
- tagParamsIdentifier,
4361
+ ...markReturn(childSection, setupIdentifier, tagParamsIdentifier),
4304
4362
  childSection.hoisted || childSection.isHoistThrough ? getSectionInstancesAccessorLiteral(childSection) : void 0
4305
4363
  ]));
4306
4364
  if (!registerReason || registerWrapper) renderer = _marko_compiler.types.addComment(renderer, "leading", "@__PURE__");
@@ -4323,8 +4381,7 @@ var dom_default = { translate: {
4323
4381
  program.node.body.push(_marko_compiler.types.exportDefaultDeclaration(callRuntime("_template", _marko_compiler.types.stringLiteral((0, _marko_compiler_babel_utils.getFile)().metadata.marko.id), ...replaceNullishAndEmptyFunctionsWith0([
4324
4382
  templateIdentifier,
4325
4383
  walksIdentifier,
4326
- section.hasSetupWork ? setupIdentifier : void 0,
4327
- programInputSignal?.identifier
4384
+ ...markReturn(section, section.hasSetupWork ? setupIdentifier : void 0, programInputSignal?.identifier)
4328
4385
  ]))));
4329
4386
  }
4330
4387
  } };
@@ -4332,6 +4389,9 @@ function assertSetupWorkFound(program, section, written) {
4332
4389
  const setup = getSetup(section);
4333
4390
  if (!section.hasSetupWork && setup && written.has(setup)) throw program.buildCodeFrameError("Marko internal error: analysis found no setup work for a section whose translation produced setup statements. Please open an issue with a reproduction.");
4334
4391
  }
4392
+ function markReturn(section, setup, params) {
4393
+ return section.returnValueExpr && !isOptimize() ? setup ? [callRuntime("_return_setup", setup), params] : [setup, callRuntime("_return_setup", params)] : [setup, params];
4394
+ }
4335
4395
  //#endregion
4336
4396
  //#region src/translator/visitors/program/html.ts
4337
4397
  function getTemplateContentName() {
@@ -4339,11 +4399,11 @@ function getTemplateContentName() {
4339
4399
  }
4340
4400
  var html_default = { translate: {
4341
4401
  enter() {
4402
+ const sectionDynamicSubscribers = /* @__PURE__ */ new Set();
4342
4403
  forEachSection((section) => {
4343
4404
  forEach(section.bindings, (binding) => {
4344
4405
  for (const [hoistSection, hasReference] of binding.getters) if (hasReference) getHTMLSectionStatements(hoistSection || section).push(_marko_compiler.types.variableDeclaration("const", [hoistSection ? _marko_compiler.types.variableDeclarator(getBindingGetterIdentifier(binding, hoistSection), callRuntime("_hoist", getScopeIdIdentifier(hoistSection), _marko_compiler.types.stringLiteral(getResumeRegisterId(hoistSection, binding, "hoist")))) : _marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(binding.originalName), callRuntime("_el", getScopeIdIdentifier(section), _marko_compiler.types.stringLiteral(getResumeRegisterId(section, binding))))]));
4345
4406
  });
4346
- const sectionDynamicSubscribers = /* @__PURE__ */ new Set();
4347
4407
  forEach(section.hoisted, (binding) => {
4348
4408
  let highestHoistSection;
4349
4409
  forEach(binding.hoists, (hoistSection) => {
@@ -4501,7 +4561,7 @@ function initBranchSection(bodySection, branchExpr, branch) {
4501
4561
  }
4502
4562
  function resumeOwnerByMarkerWhenStatic(bodySection, nodeBinding) {
4503
4563
  const branchExprReason = findSlot(nodeBinding, 4)?.reason;
4504
- if (isStateReason(branchExprReason) && some(branchExprReason.state, hasResumableWriter) && isUnconditionalReason(findSectionSlot(bodySection, 9)?.reason) && isUnconditionalReason(findSlot(nodeBinding)?.reason)) setSectionOwnerResumedByMarker(bodySection);
4564
+ if (isStateReason(branchExprReason) && some(branchExprReason.state, hasResumableWriter) && isUnconditionalReason(getBranchWriteReason(bodySection)) && isUnconditionalReason(getWriteReason(nodeBinding))) setSectionOwnerResumedByMarker(bodySection);
4505
4565
  }
4506
4566
  function getBranchResumeArgs(tagSection, nodeBinding, branchReasons, onlyChildParentTagName, singleNode) {
4507
4567
  const endArgs = getBranchEndArgs(tagSection, nodeBinding, onlyChildParentTagName, singleNode);
@@ -4509,7 +4569,7 @@ function getBranchResumeArgs(tagSection, nodeBinding, branchReasons, onlyChildPa
4509
4569
  return [getWriteGuardForAny(tagSection, branchReasons, !markerGuard), ...endArgs];
4510
4570
  }
4511
4571
  function getBranchEndArgs(tagSection, nodeBinding, onlyChildParentTagName, singleNode) {
4512
- const markerReason = findSlot(nodeBinding)?.reason;
4572
+ const markerReason = getWriteReason(nodeBinding);
4513
4573
  const skipParentEnd = !!onlyChildParentTagName && !!markerReason;
4514
4574
  if (skipParentEnd) getBranchEndTags().add(nodeBinding);
4515
4575
  const branchExprGuard = skipParentEnd ? getWriteGuard(tagSection, findSlot(nodeBinding, 4)?.reason, false) : singleNode ? _marko_compiler.types.numericLiteral(0) : void 0;
@@ -4592,7 +4652,7 @@ const IfTag = {
4592
4652
  const [branchTag, branchBodySection] = branches[i];
4593
4653
  const bodyStatements = branchTag.node.body.body;
4594
4654
  if (branchBodySection) {
4595
- const branchReason = findSectionSlot(branchBodySection, 9)?.reason;
4655
+ const branchReason = getBranchWriteReason(branchBodySection);
4596
4656
  if (branchReason) {
4597
4657
  branchReasons = sourcesUtil.add(branchReasons, branchReason);
4598
4658
  bodyStatements.push(_marko_compiler.types.returnStatement(_marko_compiler.types.numericLiteral(i)));
@@ -4625,8 +4685,10 @@ const IfTag = {
4625
4685
  const [branchTag, branchBodySection] = branches[i];
4626
4686
  const [testAttr] = branchTag.node.attributes;
4627
4687
  const consequent = _marko_compiler.types.numericLiteral(branchBodySection ? i : -1);
4628
- if (branchBodySection) setClosureSignalBuilder(branchTag, (_closure, render) => {
4629
- return callRuntime("_if_closure", getScopeAccessorLiteral(nodeBinding, true), _marko_compiler.types.numericLiteral(i), render);
4688
+ if (branchBodySection) setClosureSignalBuilder(branchTag, {
4689
+ kind: "if",
4690
+ ref: nodeBinding,
4691
+ index: i
4630
4692
  });
4631
4693
  branchTag.remove();
4632
4694
  expr = testAttr ? _marko_compiler.types.conditionalExpression(testAttr.value, consequent, expr) : consequent;
@@ -4819,7 +4881,10 @@ var custom_tag_default = {
4819
4881
  const childSection = childExtra.section;
4820
4882
  if (childSection === programSection && getOrCreateSection(tag) === programSection) throw tag.get("name").buildCodeFrameError(`A template that renders itself outside a branch never terminates. Render \`<${getStaticTagName(tag.node)}>\` inside a branch that eventually stops, such as \`<if>\`.`);
4821
4883
  if (childExtra.page) programExtra.page ??= true;
4822
- if (tagExtra.tagNameLoad) tagExtra[kLoadTagBinding] = createBinding("#text", 0, getOrCreateSection(tag));
4884
+ if (tagExtra.tagNameLoad) {
4885
+ if (tag.node.var) throw tag.get("var").buildCodeFrameError(`The \`${getStaticTagName(tag.node)}\` tag is lazily loaded, so it does not support a [tag variable](https://markojs.com/docs/reference/language#tag-variables). Remove the variable, or import the tag without \`load\`.`);
4886
+ tagExtra[kLoadTagBinding] = createBinding("#text", 0, getOrCreateSection(tag));
4887
+ }
4823
4888
  knownTagAnalyze(tag, childSection, childExtra.paramsTree);
4824
4889
  const tagName = getStaticTagName(tag.node);
4825
4890
  if (tagExtra.tagNameLoad) {
@@ -4866,7 +4931,6 @@ function translateDOM$1(tag) {
4866
4931
  const isLoad = !!loadConfig;
4867
4932
  const tagName = getStaticTagName(node);
4868
4933
  if (isLoad) {
4869
- if (node.var) importRuntimeFeature("dynamic-tag-var");
4870
4934
  const childFileName = childFile.opts.filename;
4871
4935
  const { triggers, signals, setups } = getLoadIdentifiers();
4872
4936
  let triggerIdent = triggers.get(loadConfig);
@@ -4889,14 +4953,14 @@ function translateDOM$1(tag) {
4889
4953
  }
4890
4954
  return signalIdent;
4891
4955
  }, (section, childBinding) => {
4892
- const setupKey = `${triggerIdent ? triggerIdent.name : ""}\0${childFileName}${node.var ? "\0var" : ""}`;
4956
+ const setupKey = `${triggerIdent ? triggerIdent.name : ""}\0${childFileName}`;
4893
4957
  let setupIdent = setups.get(setupKey);
4894
4958
  if (!setupIdent) {
4895
4959
  setupIdent = generateUidIdentifier(`load_${tagName}_setup`);
4896
4960
  setups.set(setupKey, setupIdent);
4897
4961
  const setupLoadExpr = _marko_compiler.types.arrowFunctionExpression([], dynamicImport(buildLoadSetupVirtualModule(file, childFileName, childExports)));
4898
4962
  importRuntimeFeature("catch");
4899
- (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.variableDeclaration("let", [_marko_compiler.types.variableDeclarator(setupIdent, callRuntime(node.var ? "_load_setup_var" : "_load_setup", triggerIdent ? _marko_compiler.types.addComment(_marko_compiler.types.callExpression(triggerIdent, [setupLoadExpr]), "leading", "@__PURE__") : setupLoadExpr))]));
4963
+ (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.variableDeclaration("let", [_marko_compiler.types.variableDeclarator(setupIdent, callRuntime("_load_setup", triggerIdent ? _marko_compiler.types.addComment(_marko_compiler.types.callExpression(triggerIdent, [setupLoadExpr]), "leading", "@__PURE__") : setupLoadExpr))]));
4900
4964
  }
4901
4965
  addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(setupIdent, [
4902
4966
  scopeIdentifier,
@@ -5477,7 +5541,7 @@ var for_default = {
5477
5541
  const params = node.body.params;
5478
5542
  const statements = [];
5479
5543
  const bodyStatements = node.body.body;
5480
- const branchReason = findSectionSlot(bodySection, 9)?.reason;
5544
+ const branchReason = getBranchWriteReason(bodySection);
5481
5545
  resumeOwnerByMarkerWhenStatic(bodySection, nodeBinding);
5482
5546
  flushInto(tag);
5483
5547
  writeHTMLResumeStatements(tagBody);
@@ -5503,10 +5567,14 @@ var for_default = {
5503
5567
  const tagExtra = node.extra;
5504
5568
  const referencedBindings = getReferencedBindings(tagExtra);
5505
5569
  const nodeBinding = tagExtra.nodeBinding;
5506
- setClosureSignalBuilder(tag, (closure, render) => {
5570
+ const hop = {
5571
+ kind: "for",
5572
+ ref: nodeBinding
5573
+ };
5574
+ setClosureSignalBuilder(tag, hop, (closure, render) => {
5507
5575
  const selectorKeyBinding = getForSelectorKey(bodySection, closure);
5508
- if (selectorKeyBinding) return callRuntime("_for_selector", getScopeAccessorLiteral(nodeBinding, true), getScopeAccessorLiteral(closure, true), getScopeAccessorLiteral(selectorKeyBinding, true), render);
5509
- return callRuntime("_for_closure", getScopeAccessorLiteral(nodeBinding, true), render);
5576
+ if (!selectorKeyBinding) return buildClosureHop(hop, render);
5577
+ return callRuntime("_for_selector", getScopeAccessorLiteral(nodeBinding, true), getScopeAccessorLiteral(closure, true), getScopeAccessorLiteral(selectorKeyBinding, true), render);
5510
5578
  });
5511
5579
  const forType = getForType(node);
5512
5580
  const forAttrs = getKnownAttrValues(node);
@@ -5870,6 +5938,7 @@ function knownTagAnalyze(tag, contentSection, childParamsTree) {
5870
5938
  else exprs = analyzeKnownTagParams(tag, getParamsTree(contentSection));
5871
5939
  } else exprs = analyzeKnownTagParams(tag, childParamsTree);
5872
5940
  if (varBinding) {
5941
+ if (!recursive) assertReturns(tag, contentSection);
5873
5942
  addSetupExpr(section);
5874
5943
  const mutatesTagVar = !!(tag.node.var.type === "Identifier" && tag.scope.getBinding(tag.node.var.name)?.constantViolations.length);
5875
5944
  const varExpr = recursive || (tagExtra.defineBodySection ? contentSection.returnValueExpr : mapParamReasonToExpr(exprs, getReturnParams(contentSection)));
@@ -5882,7 +5951,11 @@ function knownTagAnalyze(tag, contentSection, childParamsTree) {
5882
5951
  }
5883
5952
  }
5884
5953
  function analyzeRecursiveTags() {
5885
- for (const tag of getRecursiveTags()) analyzeKnownTagParams(tag, getParamsTree(tag.node.extra[kContentSection]));
5954
+ for (const tag of getRecursiveTags()) {
5955
+ const contentSection = tag.node.extra[kContentSection];
5956
+ if (tag.node.var) assertReturns(tag, contentSection);
5957
+ analyzeKnownTagParams(tag, getParamsTree(contentSection));
5958
+ }
5886
5959
  }
5887
5960
  function getParamsTree(contentSection) {
5888
5961
  return contentSection.params && getBindingPropTree(contentSection.params, true);
@@ -5897,9 +5970,12 @@ function analyzeKnownTagParams(tag, propTree) {
5897
5970
  return exprs;
5898
5971
  }
5899
5972
  function getReturnParams(section) {
5900
- const sources = section.returnValueExpr && getSourcesForExpr(section.returnValueExpr);
5973
+ const sources = getSourcesForExpr(section.returnValueExpr);
5901
5974
  return sources && (sources.always || !!sources.state || sources.param);
5902
5975
  }
5976
+ function assertReturns(tag, contentSection) {
5977
+ if (!contentSection.returnValueExpr) throw tag.get("var").buildCodeFrameError(`The \`${getStaticTagName(tag.node)}\` tag does not [\`<return>\`](https://markojs.com/docs/reference/core-tag#return) a value, so it does not support a [tag variable](https://markojs.com/docs/reference/language#tag-variables). Remove the variable, or add a \`<return>\` to the tag.`);
5978
+ }
5903
5979
  function isChildScopeResumed(tagExtra) {
5904
5980
  return !!findSlot(tagExtra.nodeBinding)?.reason;
5905
5981
  }
@@ -6543,7 +6619,7 @@ function resolveReads(intersectionsBySection) {
6543
6619
  }
6544
6620
  forEach(exprBindings.lazyBindings, addAlwaysRead);
6545
6621
  } else forEach(reads, (read) => {
6546
- if (!read.inFunction && read.extra.exprRoot?.retained) addReasonExprs(getSlot(read.binding), expr);
6622
+ if (!read.fnRoot && read.extra.exprRoot?.retained) addReasonExprs(getSlot(read.binding), expr);
6547
6623
  });
6548
6624
  if (exprBindings.allBindings) {
6549
6625
  const exprFnReads = fnReadsByExpression.get(expr);
@@ -7062,6 +7138,9 @@ function getValueReason(extra) {
7062
7138
  }
7063
7139
  return reason;
7064
7140
  }
7141
+ function getReasonForExpr(extra) {
7142
+ return readersOfExtra(extra).reason;
7143
+ }
7065
7144
  function readersOfExtra(extra) {
7066
7145
  if (extra.isEffect) return ALWAYS_READ;
7067
7146
  const readers = extraReaders(extra);
@@ -7909,7 +7988,7 @@ function addRead(exprExtra, extra, binding, section, getter) {
7909
7988
  ownVar: false,
7910
7989
  comparedTo: void 0,
7911
7990
  deferred: false,
7912
- inFunction: false
7991
+ fnRoot: void 0
7913
7992
  };
7914
7993
  if (section.pruned) return read;
7915
7994
  binding.reads.set(exprExtra, push(binding.reads.get(exprExtra), read));
@@ -7984,7 +8063,6 @@ function addReadToExpression(root, binding, getter) {
7984
8063
  }
7985
8064
  if (!getter && root.parent.type === "MarkoSpreadAttribute") extra.spreadFrom = binding;
7986
8065
  if (fnRoot) {
7987
- read.inFunction = true;
7988
8066
  read.deferred = fnRoot.node.type !== "ObjectMethod" || fnRoot.node.kind === "method";
7989
8067
  const fnReadsByExpr = getFunctionReadsByExpression();
7990
8068
  let exprFnReads = fnReadsByExpr.get(exprExtra);
@@ -7992,6 +8070,7 @@ function addReadToExpression(root, binding, getter) {
7992
8070
  const fnExtra = fnRoot.node.extra ??= {};
7993
8071
  fnExtra.section = section;
7994
8072
  fnExtra.exprRoot = rootExtra;
8073
+ read.fnRoot = fnExtra;
7995
8074
  exprFnReads.set(fnExtra, push(exprFnReads.get(fnExtra), read));
7996
8075
  }
7997
8076
  }
@@ -8792,7 +8871,7 @@ var html_comment_default = {
8792
8871
  const textLiteral = bodyToTextLiteral(tag.node.body);
8793
8872
  if (!_marko_compiler.types.isStringLiteral(textLiteral)) addStatement("render", tagSection, getReferencedBindings(tagExtra), _marko_compiler.types.expressionStatement(callRuntime("_text", createScopeReadExpression(nodeBinding), textLiteral)));
8794
8873
  }
8795
- if (nodeBinding) markNode(tag, nodeBinding, findSlot(nodeBinding)?.reason);
8874
+ if (nodeBinding) markNode(tag, nodeBinding, getWriteReason(nodeBinding));
8796
8875
  tag.remove();
8797
8876
  } },
8798
8877
  parseOptions: { text: true },
@@ -9283,11 +9362,12 @@ var show_default = {
9283
9362
  const singleNode = tagExtra[kSingleNodeBody];
9284
9363
  const endArgs = getBranchEndArgs(tagSection, nodeBinding, onlyChildParentTagName, singleNode);
9285
9364
  const showStart = singleNode ? callRuntime("_show_start", _marko_compiler.types.cloneNode(display, true), _marko_compiler.types.numericLiteral(0)) : callRuntime("_show_start", _marko_compiler.types.cloneNode(display, true), ...getBranchEndArgs(tagSection, nodeBinding, onlyChildParentTagName, singleNode));
9286
- for (const replacement of tag.replaceWithMultiple([
9365
+ const statements = [
9287
9366
  _marko_compiler.types.expressionStatement(showStart),
9288
9367
  ...bodyStatements,
9289
9368
  _marko_compiler.types.expressionStatement(callRuntime("_show_end", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), display, ...endArgs))
9290
- ])) replacement.skip();
9369
+ ];
9370
+ for (const replacement of tag.replaceWithMultiple(statements)) replacement.skip();
9291
9371
  }
9292
9372
  },
9293
9373
  dom: { exit(tag) {
@@ -9536,7 +9616,7 @@ function translateHTML(tag) {
9536
9616
  const binding = node.extra?.nodeBinding;
9537
9617
  if (binding) {
9538
9618
  writeTo$1(tag)`${callRuntime("_style_html", buildStyleDecls(node))}`;
9539
- markNode(tag, binding, findSlot(binding)?.reason);
9619
+ markNode(tag, binding, getWriteReason(binding));
9540
9620
  }
9541
9621
  emitStyleImport(tag);
9542
9622
  tag.remove();
@@ -9682,7 +9762,16 @@ var try_default = {
9682
9762
  const placeholderSection = placeholderTag && getSectionForBody(placeholderTag.get("body"));
9683
9763
  flushInto(tag);
9684
9764
  writeHTMLResumeStatements(tagBody);
9685
- tag.replaceWith(_marko_compiler.types.expressionStatement(callRuntime("_try", getScopeIdIdentifier(section), getScopeAccessorLiteral(nodeBinding), buildContent(tagBody), placeholderSection && buildContent(placeholderTag.get("body")), catchTag && (catchSection ? buildContent(catchTag.get("body")) : _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([]))), placeholderSection && _marko_compiler.types.stringLiteral(getResumeRegisterId(placeholderSection, "content")), catchTag && _marko_compiler.types.stringLiteral(catchSection ? getResumeRegisterId(catchSection, "content") : getEmptyCatchId(section, nodeBinding)))))[0].skip();
9765
+ const tryArgs = [
9766
+ getScopeIdIdentifier(section),
9767
+ getScopeAccessorLiteral(nodeBinding),
9768
+ buildContent(tagBody),
9769
+ placeholderSection && buildContent(placeholderTag.get("body")),
9770
+ catchTag && (catchSection ? buildContent(catchTag.get("body")) : _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([]))),
9771
+ placeholderSection && _marko_compiler.types.stringLiteral(getResumeRegisterId(placeholderSection, "content")),
9772
+ catchTag && _marko_compiler.types.stringLiteral(catchSection ? getResumeRegisterId(catchSection, "content") : getEmptyCatchId(section, nodeBinding))
9773
+ ];
9774
+ tag.replaceWith(_marko_compiler.types.expressionStatement(callRuntime("_try", ...tryArgs)))[0].skip();
9686
9775
  }
9687
9776
  },
9688
9777
  dom: { exit(tag) {
@@ -9909,7 +9998,7 @@ function translateExit(placeholder) {
9909
9998
  } else {
9910
9999
  const section = getSection(placeholder);
9911
10000
  const siblingText = extra[kSiblingText];
9912
- const markerReason = nodeBinding && findSlot(nodeBinding)?.reason;
10001
+ const markerReason = nodeBinding && getWriteReason(nodeBinding);
9913
10002
  if (isHTML) {
9914
10003
  if (markerReason) {
9915
10004
  const guard = getWriteGuard(section, markerReason, true);
@@ -10190,7 +10279,7 @@ var native_tag_default = {
10190
10279
  } else {
10191
10280
  assertValidNativeEventHandlerAttr(tag, attr);
10192
10281
  if (isChangeHandlerAttr) valueExtra.retained = true;
10193
- if (!isStaticDelimitedAttr(tag, attr) && !evaluate(attr.value).confident) {
10282
+ if (isDynamicAttr(tag, attr)) {
10194
10283
  hasDynamicAttributes = true;
10195
10284
  addSetupExpr(tagSection, attr.value);
10196
10285
  } else if (attr.name === "content" && tagName !== "meta") addSetupExpr(tagSection, attr.value);
@@ -10397,9 +10486,9 @@ var native_tag_default = {
10397
10486
  else if (contentAttr) {
10398
10487
  write`>`;
10399
10488
  htmlContentAttrTags.add(tag.node);
10400
- tag.node.body.body = [_marko_compiler.types.expressionStatement(callRuntime("_attr_content", visitAccessor, getScopeIdIdentifier(tagSection), contentAttr.value, getWriteGuard(tagSection, nodeBinding && findSlot(nodeBinding)?.reason, true)))];
10489
+ tag.node.body.body = [_marko_compiler.types.expressionStatement(callRuntime("_attr_content", visitAccessor, getScopeIdIdentifier(tagSection), contentAttr.value, getWriteGuard(tagSection, nodeBinding && getWriteReason(nodeBinding), true)))];
10401
10490
  } else if (spreadContent) {
10402
- const markerGuard = getWriteGuard(tagSection, nodeBinding && findSlot(nodeBinding)?.reason, true);
10491
+ const markerGuard = getWriteGuard(tagSection, nodeBinding && getWriteReason(nodeBinding), true);
10403
10492
  htmlContentAttrTags.add(tag.node);
10404
10493
  tag.node.body.body = [skipExpression ? _marko_compiler.types.expressionStatement(callRuntime("_attrs_partial_content", spreadExpression, skipExpression, visitAccessor, getScopeIdIdentifier(tagSection), _marko_compiler.types.stringLiteral(tagName), markerGuard)) : _marko_compiler.types.expressionStatement(callRuntime("_attrs_content", spreadExpression, visitAccessor, getScopeIdIdentifier(tagSection), _marko_compiler.types.stringLiteral(tagName), markerGuard))];
10405
10494
  } else write`>`;
@@ -10413,7 +10502,7 @@ var native_tag_default = {
10413
10502
  const tagName = getCanonicalTagName(tag);
10414
10503
  const tagSection = getSection(tag);
10415
10504
  const skipEndTag = isEndTagWrittenByBranch(nodeBinding);
10416
- const markerReason = !skipEndTag && nodeBinding && findSlot(nodeBinding)?.reason;
10505
+ const markerReason = !skipEndTag && nodeBinding && getWriteReason(nodeBinding);
10417
10506
  const write = writeTo$1(tag, tagName === "html" || !markerReason && tagName === "body");
10418
10507
  if (htmlContentAttrTags.has(tag.node)) flushBefore(tag);
10419
10508
  if (selectArgs) {
@@ -10895,6 +10984,9 @@ function assertUniqueClassToggles(tag, attr, { staticParts, dynamicValues = [] }
10895
10984
  function getClassNames(part) {
10896
10985
  return part === void 0 ? [] : isLiteralPart(part) ? part.split(/\s+/).filter(Boolean) : [part.join(".")];
10897
10986
  }
10987
+ function isDynamicAttr(tag, attr) {
10988
+ return !isStaticDelimitedAttr(tag, attr) && !evaluate(attr.value).confident;
10989
+ }
10898
10990
  function isStaticDelimitedAttr(tag, attr) {
10899
10991
  const { name, value } = attr;
10900
10992
  if (name !== "class" && name !== "style") return false;
@@ -11116,7 +11208,7 @@ var dynamic_tag_default = {
11116
11208
  const tagExtra = node.extra;
11117
11209
  const nodeBinding = tagExtra.nodeBinding;
11118
11210
  const isClassAPI = tagExtra.featureType === "class";
11119
- const markerReason = findSlot(nodeBinding)?.reason;
11211
+ const markerReason = getWriteReason(nodeBinding);
11120
11212
  let tagExpression = node.name;
11121
11213
  if (isClassAPI) {
11122
11214
  const classTagTemplate = (0, _marko_compiler_babel_utils.getTagTemplate)(tag);
@@ -11164,7 +11256,8 @@ var dynamic_tag_default = {
11164
11256
  flushInto(tag);
11165
11257
  writeHTMLResumeStatements(tag.get("body"));
11166
11258
  const markerGuard = getWriteGuard(tagSection, markerReason, true);
11167
- const dynamicTagExpr = hasTagArgs ? callRuntime("_dynamic_tag", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), tagExpression, _marko_compiler.types.arrayExpression(args), contentProp ? contentProp.value : _marko_compiler.types.numericLiteral(0), _marko_compiler.types.numericLiteral(1), markerGuard) : callRuntime("_dynamic_tag", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), tagExpression, args[0], args[1] || (markerGuard ? _marko_compiler.types.numericLiteral(0) : void 0), markerGuard ? _marko_compiler.types.numericLiteral(0) : void 0, markerGuard);
11259
+ const debugTagVar = !isOptimize() && node.var && _marko_compiler.types.numericLiteral(1);
11260
+ const dynamicTagExpr = hasTagArgs ? callRuntime("_dynamic_tag", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), tagExpression, _marko_compiler.types.arrayExpression(args), contentProp ? contentProp.value : _marko_compiler.types.numericLiteral(0), _marko_compiler.types.numericLiteral(1), markerGuard, debugTagVar) : callRuntime("_dynamic_tag", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), tagExpression, args[0], args[1] || (markerGuard ? _marko_compiler.types.numericLiteral(0) : void 0), markerGuard ? _marko_compiler.types.numericLiteral(0) : void 0, markerGuard, debugTagVar);
11168
11261
  if (node.var && isTagVarResumed(tag)) {
11169
11262
  const dynamicScopeIdentifier = generateUidIdentifier(tag.get("name").toString() + "_scope");
11170
11263
  const mutatesTagVar = isTagVarAssigned(tag);
@@ -11566,13 +11659,13 @@ function createInteropTranslator(translate5) {
11566
11659
  const entryFile = (0, _marko_compiler_babel_utils.getFile)();
11567
11660
  const { output, entry } = entryFile.markoOpts;
11568
11661
  if (!(output === "dom" && entry === "page" || output === "hydrate")) return enterProgram?.call(this, program, state);
11569
- const visitedFiles = /* @__PURE__ */ new Map([[(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, entryFile.opts.filename), false]]);
11570
- entryBuilder.visit(entryFile, entryFile, function visitChild(resolved, bundled = false) {
11571
- const seenBundled = visitedFiles.get(resolved);
11572
- if (seenBundled === false || seenBundled && bundled) return;
11573
- visitedFiles.set(resolved, bundled);
11662
+ const visitedFiles = /* @__PURE__ */ new Map([[(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, entryFile.opts.filename), 0]]);
11663
+ entryBuilder.visit(entryFile, entryFile, function visitChild(resolved, reach = 0) {
11664
+ const seen = visitedFiles.get(resolved);
11665
+ if (seen !== void 0 && seen <= reach) return;
11666
+ visitedFiles.set(resolved, reach);
11574
11667
  const file = (0, _marko_compiler_babel_utils.loadFileForImport)(entryFile, resolved);
11575
- if (file) entryBuilder.visit(file, entryFile, (id, childBundled = false) => visitChild(resolveRelativeToEntry(entryFile, file, id), childBundled || bundled));
11668
+ if (file) entryBuilder.visit(file, entryFile, (id, childReach = 0) => visitChild(resolveRelativeToEntry(entryFile, file, id), childReach > reach ? childReach : reach));
11576
11669
  });
11577
11670
  program.node.body = entryBuilder.build(entryFile);
11578
11671
  program.skip();