marko 6.4.3 → 6.4.4

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 (70) 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 +24 -16
  29. package/dist/debug/html.mjs +24 -16
  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 +7 -7
  63. package/dist/html.mjs +7 -7
  64. package/dist/translator/index.js +119 -66
  65. package/dist/translator/util/module-registrations.d.ts +1 -1
  66. package/dist/translator/util/solve-reasons.d.ts +1 -0
  67. package/dist/translator/visitors/function.d.ts +15 -10
  68. package/dist/translator/visitors/import-declaration.d.ts +3 -4
  69. package/package.json +3 -3
  70. 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
+ }
993
1003
  }
994
1004
  /**
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
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());
1014
+ }
1015
+ /**
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",
@@ -1890,19 +1923,20 @@ function escapeRegExp(str) {
1890
1923
  /**
1891
1924
  * Writes the registrations for module scoped functions: the ones this template
1892
1925
  * exports and registers itself, and the ones it imports from a template that
1893
- * reserved a register id without registering it.
1926
+ * reserved a register id without registering it; and for templates it imports.
1894
1927
  */
1895
1928
  function writeModuleRegistrations(program) {
1896
1929
  const file = (0, _marko_compiler_babel_utils.getFile)();
1897
1930
  const statements = [];
1898
1931
  const seen = /* @__PURE__ */ new Set();
1899
1932
  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));
1933
+ const registeredImports = _marko_compiler.types.isImportDeclaration(child) && child.extra?.registeredImports;
1934
+ if (registeredImports) for (const [local, registered] of registeredImports) {
1935
+ if (seen.has(registered.registerId)) continue;
1936
+ seen.add(registered.registerId);
1937
+ if (isOutputHTML()) {
1938
+ if (registered.exportName !== "default") statements.push(buildRegistration(local, registered.registerId));
1939
+ } else (0, _marko_compiler_babel_utils.importDefault)(file, resolveRegisterModule(file, registered));
1906
1940
  }
1907
1941
  else if (child.type === "ExportNamedDeclaration") addExportRegistrations(child, seen, statements);
1908
1942
  }
@@ -1933,7 +1967,7 @@ function resolveRegisterModule(file, { filename, exportName, registerId }) {
1933
1967
  const importer = file.opts.filename;
1934
1968
  return getMarkoOpts().resolveVirtualDependency(importer, {
1935
1969
  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`
1970
+ 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
1971
  });
1938
1972
  }
1939
1973
  function relativePath(from, to) {
@@ -2157,7 +2191,7 @@ var import_declaration_default = {
2157
2191
  if (tagImport) {
2158
2192
  const tags = (0, _marko_compiler_babel_utils.getFile)().metadata.marko.tags;
2159
2193
  if (!tags.includes(tagImport)) tags.push(tagImport);
2160
- trackImportedRegisteredFns(importDecl);
2194
+ trackRegisteredImports(importDecl);
2161
2195
  }
2162
2196
  const loadAttrPath = getLoadAttr(importDecl);
2163
2197
  if (loadAttrPath) {
@@ -2198,7 +2232,9 @@ var import_declaration_default = {
2198
2232
  } else if (binding.referencePaths.every((ref) => _marko_compiler.types.isMarkoTag(ref.parent) && ref.parent.extra?.tagNameLoad)) importDecl.remove();
2199
2233
  else {
2200
2234
  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"))))))]));
2235
+ 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"))));
2236
+ const args = [_marko_compiler.types.stringLiteral(loadFile.metadata.marko.id), load];
2237
+ 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
2238
  }
2203
2239
  return;
2204
2240
  }
@@ -2230,17 +2266,19 @@ function getOrCreateHtmlLoadWrapped(readyId, originalIdentifier, filename, trigg
2230
2266
  (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
2267
  return wrappedName;
2232
2268
  }
2233
- function trackImportedRegisteredFns(importDecl) {
2269
+ function trackRegisteredImports(importDecl) {
2234
2270
  const { node } = importDecl;
2235
2271
  const childFile = (0, _marko_compiler_babel_utils.loadFileForImport)((0, _marko_compiler_babel_utils.getFile)(), node.source.value);
2236
2272
  if (!childFile) return;
2237
2273
  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);
2274
+ let importedName = "default";
2275
+ if (specifier.isImportSpecifier()) {
2276
+ const { imported } = specifier.node;
2277
+ importedName = imported.type === "Identifier" ? imported.name : imported.value;
2278
+ } else if (!specifier.isImportDefaultSpecifier()) continue;
2279
+ const local = specifier.node.local.name;
2280
+ if (importedName === "default") trackImportedTemplate(importDecl, local, childFile);
2281
+ else trackImport(importDecl, local, resolveRegisteredExport(childFile, importedName));
2244
2282
  }
2245
2283
  }
2246
2284
  function getLoadAttr(importDecl) {
@@ -4299,8 +4337,7 @@ var dom_default = { translate: {
4299
4337
  let renderer = callRuntime("_content", _marko_compiler.types.stringLiteral(registerId), ...replaceNullishAndEmptyFunctionsWith0([
4300
4338
  writes,
4301
4339
  walks,
4302
- setupIdentifier,
4303
- tagParamsIdentifier,
4340
+ ...markReturn(childSection, setupIdentifier, tagParamsIdentifier),
4304
4341
  childSection.hoisted || childSection.isHoistThrough ? getSectionInstancesAccessorLiteral(childSection) : void 0
4305
4342
  ]));
4306
4343
  if (!registerReason || registerWrapper) renderer = _marko_compiler.types.addComment(renderer, "leading", "@__PURE__");
@@ -4323,8 +4360,7 @@ var dom_default = { translate: {
4323
4360
  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
4361
  templateIdentifier,
4325
4362
  walksIdentifier,
4326
- section.hasSetupWork ? setupIdentifier : void 0,
4327
- programInputSignal?.identifier
4363
+ ...markReturn(section, section.hasSetupWork ? setupIdentifier : void 0, programInputSignal?.identifier)
4328
4364
  ]))));
4329
4365
  }
4330
4366
  } };
@@ -4332,6 +4368,9 @@ function assertSetupWorkFound(program, section, written) {
4332
4368
  const setup = getSetup(section);
4333
4369
  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
4370
  }
4371
+ function markReturn(section, setup, params) {
4372
+ return section.returnValueExpr && !isOptimize() ? setup ? [callRuntime("_return_setup", setup), params] : [setup, callRuntime("_return_setup", params)] : [setup, params];
4373
+ }
4335
4374
  //#endregion
4336
4375
  //#region src/translator/visitors/program/html.ts
4337
4376
  function getTemplateContentName() {
@@ -4339,11 +4378,11 @@ function getTemplateContentName() {
4339
4378
  }
4340
4379
  var html_default = { translate: {
4341
4380
  enter() {
4381
+ const sectionDynamicSubscribers = /* @__PURE__ */ new Set();
4342
4382
  forEachSection((section) => {
4343
4383
  forEach(section.bindings, (binding) => {
4344
4384
  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
4385
  });
4346
- const sectionDynamicSubscribers = /* @__PURE__ */ new Set();
4347
4386
  forEach(section.hoisted, (binding) => {
4348
4387
  let highestHoistSection;
4349
4388
  forEach(binding.hoists, (hoistSection) => {
@@ -4819,7 +4858,10 @@ var custom_tag_default = {
4819
4858
  const childSection = childExtra.section;
4820
4859
  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
4860
  if (childExtra.page) programExtra.page ??= true;
4822
- if (tagExtra.tagNameLoad) tagExtra[kLoadTagBinding] = createBinding("#text", 0, getOrCreateSection(tag));
4861
+ if (tagExtra.tagNameLoad) {
4862
+ 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\`.`);
4863
+ tagExtra[kLoadTagBinding] = createBinding("#text", 0, getOrCreateSection(tag));
4864
+ }
4823
4865
  knownTagAnalyze(tag, childSection, childExtra.paramsTree);
4824
4866
  const tagName = getStaticTagName(tag.node);
4825
4867
  if (tagExtra.tagNameLoad) {
@@ -4866,7 +4908,6 @@ function translateDOM$1(tag) {
4866
4908
  const isLoad = !!loadConfig;
4867
4909
  const tagName = getStaticTagName(node);
4868
4910
  if (isLoad) {
4869
- if (node.var) importRuntimeFeature("dynamic-tag-var");
4870
4911
  const childFileName = childFile.opts.filename;
4871
4912
  const { triggers, signals, setups } = getLoadIdentifiers();
4872
4913
  let triggerIdent = triggers.get(loadConfig);
@@ -4889,14 +4930,14 @@ function translateDOM$1(tag) {
4889
4930
  }
4890
4931
  return signalIdent;
4891
4932
  }, (section, childBinding) => {
4892
- const setupKey = `${triggerIdent ? triggerIdent.name : ""}\0${childFileName}${node.var ? "\0var" : ""}`;
4933
+ const setupKey = `${triggerIdent ? triggerIdent.name : ""}\0${childFileName}`;
4893
4934
  let setupIdent = setups.get(setupKey);
4894
4935
  if (!setupIdent) {
4895
4936
  setupIdent = generateUidIdentifier(`load_${tagName}_setup`);
4896
4937
  setups.set(setupKey, setupIdent);
4897
4938
  const setupLoadExpr = _marko_compiler.types.arrowFunctionExpression([], dynamicImport(buildLoadSetupVirtualModule(file, childFileName, childExports)));
4898
4939
  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))]));
4940
+ (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
4941
  }
4901
4942
  addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(setupIdent, [
4902
4943
  scopeIdentifier,
@@ -5870,6 +5911,7 @@ function knownTagAnalyze(tag, contentSection, childParamsTree) {
5870
5911
  else exprs = analyzeKnownTagParams(tag, getParamsTree(contentSection));
5871
5912
  } else exprs = analyzeKnownTagParams(tag, childParamsTree);
5872
5913
  if (varBinding) {
5914
+ if (!recursive) assertReturns(tag, contentSection);
5873
5915
  addSetupExpr(section);
5874
5916
  const mutatesTagVar = !!(tag.node.var.type === "Identifier" && tag.scope.getBinding(tag.node.var.name)?.constantViolations.length);
5875
5917
  const varExpr = recursive || (tagExtra.defineBodySection ? contentSection.returnValueExpr : mapParamReasonToExpr(exprs, getReturnParams(contentSection)));
@@ -5882,7 +5924,11 @@ function knownTagAnalyze(tag, contentSection, childParamsTree) {
5882
5924
  }
5883
5925
  }
5884
5926
  function analyzeRecursiveTags() {
5885
- for (const tag of getRecursiveTags()) analyzeKnownTagParams(tag, getParamsTree(tag.node.extra[kContentSection]));
5927
+ for (const tag of getRecursiveTags()) {
5928
+ const contentSection = tag.node.extra[kContentSection];
5929
+ if (tag.node.var) assertReturns(tag, contentSection);
5930
+ analyzeKnownTagParams(tag, getParamsTree(contentSection));
5931
+ }
5886
5932
  }
5887
5933
  function getParamsTree(contentSection) {
5888
5934
  return contentSection.params && getBindingPropTree(contentSection.params, true);
@@ -5897,9 +5943,12 @@ function analyzeKnownTagParams(tag, propTree) {
5897
5943
  return exprs;
5898
5944
  }
5899
5945
  function getReturnParams(section) {
5900
- const sources = section.returnValueExpr && getSourcesForExpr(section.returnValueExpr);
5946
+ const sources = getSourcesForExpr(section.returnValueExpr);
5901
5947
  return sources && (sources.always || !!sources.state || sources.param);
5902
5948
  }
5949
+ function assertReturns(tag, contentSection) {
5950
+ 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.`);
5951
+ }
5903
5952
  function isChildScopeResumed(tagExtra) {
5904
5953
  return !!findSlot(tagExtra.nodeBinding)?.reason;
5905
5954
  }
@@ -7062,6 +7111,9 @@ function getValueReason(extra) {
7062
7111
  }
7063
7112
  return reason;
7064
7113
  }
7114
+ function getReasonForExpr(extra) {
7115
+ return readersOfExtra(extra).reason;
7116
+ }
7065
7117
  function readersOfExtra(extra) {
7066
7118
  if (extra.isEffect) return ALWAYS_READ;
7067
7119
  const readers = extraReaders(extra);
@@ -11164,7 +11216,8 @@ var dynamic_tag_default = {
11164
11216
  flushInto(tag);
11165
11217
  writeHTMLResumeStatements(tag.get("body"));
11166
11218
  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);
11219
+ const debugTagVar = !isOptimize() && node.var && _marko_compiler.types.numericLiteral(1);
11220
+ 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
11221
  if (node.var && isTagVarResumed(tag)) {
11169
11222
  const dynamicScopeIdentifier = generateUidIdentifier(tag.get("name").toString() + "_scope");
11170
11223
  const mutatesTagVar = isTagVarAssigned(tag);
@@ -2,6 +2,6 @@ import { types as t } from "@marko/compiler";
2
2
  /**
3
3
  * Writes the registrations for module scoped functions: the ones this template
4
4
  * exports and registers itself, and the ones it imports from a template that
5
- * reserved a register id without registering it.
5
+ * reserved a register id without registering it; and for templates it imports.
6
6
  */
7
7
  export declare function writeModuleRegistrations(program: t.NodePath<t.Program>): void;
@@ -6,5 +6,6 @@ import { type Section } from "./sections";
6
6
  export declare function solveReasons(intersectionsBySection: Map<Section, Intersection[]>): void;
7
7
  export declare function getReasonForBinding(binding: Binding, properties?: Opt<string> | true): undefined | Reason;
8
8
  export declare function getValueReason(extra: t.NodeExtra): undefined | Reason;
9
+ export declare function getReasonForExpr(extra: t.NodeExtra): undefined | Reason;
9
10
  export declare function readsValuesOnResume(expr: t.NodeExtra): boolean;
10
11
  export declare function addAlwaysRead(binding: Binding): void;
@@ -2,16 +2,16 @@ import { types as t } from "@marko/compiler";
2
2
  declare const kRegisteredExports: unique symbol;
3
3
  declare module "@marko/compiler/dist/types" {
4
4
  interface ProgramExtra {
5
- [kRegisteredExports]?: Map<string, ReservedExport>;
5
+ [kRegisteredExports]?: Map<string, RegisteredExport>;
6
6
  }
7
7
  }
8
- /** The canonical name a reserved register id is exported under, and its id. */
9
- export interface ReservedExport {
8
+ /**
9
+ * An export registered under an id: the template that declares it, and the
10
+ * canonical name it is exported under.
11
+ */
12
+ export interface RegisteredExport {
10
13
  registerId: string;
11
14
  exportName: string;
12
- }
13
- /** A reserved export, plus the template that declares it. */
14
- export interface ResolvedExport extends ReservedExport {
15
15
  filename: string;
16
16
  }
17
17
  declare const _default: {
@@ -21,15 +21,20 @@ export default _default;
21
21
  export declare function resolveFunctionReason(): void;
22
22
  export declare function finalizeFunctionRegistry(): void;
23
23
  /**
24
- * Tracks a function imported from another template that reserved a register id.
25
- * The importing template registers it (under the reserved id) when client
24
+ * Tracks a template imported as a default export. The server writes a template
25
+ * only as a binding's value, so the importing template registers it when one may.
26
+ */
27
+ export declare function trackImportedTemplate(importDecl: t.NodePath<t.ImportDeclaration>, local: string, templateFile: t.BabelFile): void;
28
+ /**
29
+ * Tracks an export imported from another template that registers under an id,
30
+ * if it does. The importing template registers it (under that id) when client
26
31
  * code reads its own references.
27
32
  */
28
- export declare function trackImportedFn(importDecl: t.NodePath<t.ImportDeclaration>, local: string, resolved: ResolvedExport): void;
33
+ export declare function trackImport(importDecl: t.NodePath<t.ImportDeclaration>, local: string, registered: RegisteredExport | undefined, fnRoots?: Set<t.NodeExtra>): void;
29
34
  /**
30
35
  * Finds the id reserved for an export, following `export ... from` hops. Each
31
36
  * template only records the exports it declares, so this resolves on demand:
32
37
  * a template in an import cycle is read while it is still analyzing, and would
33
38
  * hand out an incomplete map if the ids were pushed ahead of time.
34
39
  */
35
- export declare function resolveRegisteredExport(file: t.BabelFile, exportName: string, seen?: Set<string>): ResolvedExport | undefined;
40
+ export declare function resolveRegisteredExport(file: t.BabelFile, exportName: string, seen?: Set<string>): RegisteredExport | undefined;
@@ -1,6 +1,6 @@
1
1
  import { types as t } from "@marko/compiler";
2
2
  import type { LoadTrigger } from "../../html/assets";
3
- import { type ResolvedExport } from "./function";
3
+ import { type RegisteredExport } from "./function";
4
4
  declare module "@marko/compiler/dist/types" {
5
5
  interface ProgramExtra {
6
6
  /** Absolute filenames of templates this one imports with `load`. */
@@ -9,9 +9,8 @@ declare module "@marko/compiler/dist/types" {
9
9
  interface ImportDeclarationExtra {
10
10
  tagImport?: string;
11
11
  loadImport?: LoadImportConfig;
12
- registeredImportedFns?: (ResolvedExport & {
13
- local: string;
14
- })[];
12
+ /** Each local binding the template registers -> the export it imports. */
13
+ registeredImports?: Map<string, RegisteredExport>;
15
14
  }
16
15
  }
17
16
  export type LoadImportConfig = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marko",
3
- "version": "6.4.3",
3
+ "version": "6.4.4",
4
4
  "description": "Optimized runtime for Marko templates.",
5
5
  "keywords": [
6
6
  "api",
@@ -51,13 +51,13 @@
51
51
  }
52
52
  },
53
53
  "dependencies": {
54
- "@marko/compiler": "^5.42.10",
54
+ "@marko/compiler": "^5.42.11",
55
55
  "csstype": "^3.2.3",
56
56
  "fastest-levenshtein": "^1.0.16",
57
57
  "magic-string": "^0.30.21"
58
58
  },
59
59
  "devDependencies": {
60
- "@marko/runtime-tags": "npm:marko@6.4.3",
60
+ "@marko/runtime-tags": "npm:marko@6.4.4",
61
61
  "marko": "5.39.45"
62
62
  },
63
63
  "engines": {
package/tags-html.d.ts CHANGED
@@ -5939,10 +5939,11 @@ interface CommonAttributes<T extends Element> {
5939
5939
  type AttrMissing = undefined | null | false;
5940
5940
  type AttrClass =
5941
5941
  | AttrMissing
5942
+ | 0
5942
5943
  | string
5943
5944
  | AttrClass[]
5944
- | Record<string, AttrMissing | boolean>;
5945
- type AttrStyle = AttrMissing | string | Marko.CSS.Properties | AttrStyle[];
5945
+ | Record<string, AttrMissing | boolean | number>;
5946
+ type AttrStyle = AttrMissing | 0 | string | Marko.CSS.Properties | AttrStyle[];
5946
5947
  type AttrCrossOrigin = AttrBoolean | "anonymous" | "use-credentials";
5947
5948
  type AttrEventHandler<Event, Target> =
5948
5949
  | AttrMissing