marko 6.4.1 → 6.4.3

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 (80) hide show
  1. package/cheatsheet.md +1 -1
  2. package/dist/common/constants/accessor-prop.d.ts +1 -0
  3. package/dist/common/constants/accessor-prop.debug.d.ts +1 -0
  4. package/dist/common/errors.d.ts +1 -0
  5. package/dist/common/opt.d.ts +1 -0
  6. package/dist/common/types.d.ts +1 -0
  7. package/dist/debug/dom/catch.feat.js +1 -1
  8. package/dist/debug/dom/catch.feat.mjs +1 -1
  9. package/dist/debug/dom/controllable-input.feat.js +1 -1
  10. package/dist/debug/dom/controllable-input.feat.mjs +1 -1
  11. package/dist/debug/dom/controllable-open.feat.js +1 -1
  12. package/dist/debug/dom/controllable-open.feat.mjs +1 -1
  13. package/dist/debug/dom/controllable-select.feat.js +1 -1
  14. package/dist/debug/dom/controllable-select.feat.mjs +1 -1
  15. package/dist/debug/dom/controllable-textarea.feat.js +1 -1
  16. package/dist/debug/dom/controllable-textarea.feat.mjs +1 -1
  17. package/dist/debug/dom/controllable.feat.js +1 -1
  18. package/dist/debug/dom/controllable.feat.mjs +1 -1
  19. package/dist/debug/dom/dynamic-tag-script.feat.js +1 -1
  20. package/dist/debug/dom/dynamic-tag-script.feat.mjs +1 -1
  21. package/dist/debug/dom/dynamic-tag-var.feat.js +6 -2
  22. package/dist/debug/dom/dynamic-tag-var.feat.mjs +6 -2
  23. package/dist/debug/dom/lazy.feat.js +1 -1
  24. package/dist/debug/dom/lazy.feat.mjs +1 -1
  25. package/dist/debug/dom/placeholder.feat.js +1 -1
  26. package/dist/debug/dom/placeholder.feat.mjs +1 -1
  27. package/dist/debug/{dom-ClV4kVOO.js → dom-C7F3yZTh.js} +119 -24
  28. package/dist/debug/{dom-LFrKxOk5.mjs → dom-uEY0J_H9.mjs} +78 -25
  29. package/dist/debug/dom.js +16 -4
  30. package/dist/debug/dom.mjs +14 -5
  31. package/dist/debug/html.js +288 -78
  32. package/dist/debug/html.mjs +288 -79
  33. package/dist/dom/catch.feat.js +4 -4
  34. package/dist/dom/catch.feat.mjs +1 -1
  35. package/dist/dom/control-flow.d.ts +2 -2
  36. package/dist/dom/controllable-input.feat.js +2 -2
  37. package/dist/dom/controllable-input.feat.mjs +1 -1
  38. package/dist/dom/controllable-open.feat.js +2 -2
  39. package/dist/dom/controllable-open.feat.mjs +1 -1
  40. package/dist/dom/controllable-select.feat.js +2 -2
  41. package/dist/dom/controllable-select.feat.mjs +1 -1
  42. package/dist/dom/controllable-textarea.feat.js +2 -2
  43. package/dist/dom/controllable-textarea.feat.mjs +1 -1
  44. package/dist/dom/controllable.feat.js +2 -2
  45. package/dist/dom/controllable.feat.mjs +1 -1
  46. package/dist/dom/dom.d.ts +1 -0
  47. package/dist/dom/dynamic-tag-script.feat.js +2 -2
  48. package/dist/dom/dynamic-tag-script.feat.mjs +1 -1
  49. package/dist/dom/dynamic-tag-var.feat.js +4 -2
  50. package/dist/dom/dynamic-tag-var.feat.mjs +4 -3
  51. package/dist/dom/lazy.feat.js +1 -1
  52. package/dist/dom/lazy.feat.mjs +1 -1
  53. package/dist/dom/load.d.ts +1 -0
  54. package/dist/dom/placeholder.feat.js +3 -3
  55. package/dist/dom/placeholder.feat.mjs +1 -1
  56. package/dist/dom/queue.d.ts +4 -1
  57. package/dist/{dom-CNglVi8P.js → dom-CtIT8Mpr.js} +201 -138
  58. package/dist/{dom-DfP3MCo0.mjs → dom-DHg9YChM.mjs} +60 -27
  59. package/dist/dom.d.ts +3 -3
  60. package/dist/dom.js +41 -34
  61. package/dist/dom.mjs +12 -5
  62. package/dist/html/assets.d.ts +12 -6
  63. package/dist/html/attrs.d.ts +1 -0
  64. package/dist/html/compat.d.ts +10 -2
  65. package/dist/html/serializer.d.ts +1 -0
  66. package/dist/html/writer.d.ts +8 -0
  67. package/dist/html.d.ts +1 -1
  68. package/dist/html.js +207 -62
  69. package/dist/html.mjs +207 -62
  70. package/dist/translator/index.js +432 -213
  71. package/dist/translator/util/bindings.d.ts +9 -1
  72. package/dist/translator/util/constants/structure-kind.d.ts +1 -0
  73. package/dist/translator/util/known-tag.d.ts +2 -1
  74. package/dist/translator/util/module-read.d.ts +21 -0
  75. package/dist/translator/util/references.d.ts +1 -0
  76. package/dist/translator/util/runtime.d.ts +2 -0
  77. package/dist/translator/util/sections.d.ts +5 -1
  78. package/dist/translator/util/structure.d.ts +1 -0
  79. package/package.json +3 -3
  80. package/tags-html.d.ts +6 -5
@@ -156,6 +156,7 @@ var accessor_prop_debug_exports = /* @__PURE__ */ __exportAll({
156
156
  AbortScopes: () => AbortScopes$1,
157
157
  AwaitCounter: () => AwaitCounter$1,
158
158
  BranchAccessor: () => BranchAccessor$1,
159
+ BranchRenders: () => BranchRenders$1,
159
160
  BranchScopes: () => BranchScopes$2,
160
161
  CatchContent: () => CatchContent$1,
161
162
  ClosestBranch: () => ClosestBranch$1,
@@ -189,6 +190,7 @@ const AbortControllers$1 = "#AbortControllers";
189
190
  const AbortScopes$1 = "#AbortScopes";
190
191
  const AwaitCounter$1 = "#AwaitCounter";
191
192
  const BranchAccessor$1 = "#BranchAccessor";
193
+ const BranchRenders$1 = "#BranchRenders";
192
194
  const BranchScopes$2 = "#BranchScopes";
193
195
  const CatchContent$1 = "#CatchContent";
194
196
  const ClosestBranch$1 = "#ClosestBranch";
@@ -797,6 +799,11 @@ function isInvokedFunction(expr) {
797
799
  return false;
798
800
  }
799
801
  //#endregion
802
+ //#region src/translator/util/is-static.ts
803
+ function isStatic(path) {
804
+ return path.isImportDeclaration() || path.isExportDeclaration() || path.isMarkoScriptlet({ static: true });
805
+ }
806
+ //#endregion
800
807
  //#region src/translator/util/binding-has-prop.ts
801
808
  function getSectionRendererIdentifier(section) {
802
809
  return isSectionRendererElided(section) ? void 0 : _marko_compiler.types.identifier(section.name);
@@ -829,6 +836,7 @@ function getPropertyPathAlias(binding, properties) {
829
836
  const Node = "node";
830
837
  const Text = "text";
831
838
  const Child = "child";
839
+ const ModuleRead = "moduleRead";
832
840
  const SectionRef = "sectionRef";
833
841
  const ExportRef = "exportRef";
834
842
  //#endregion
@@ -968,7 +976,7 @@ var function_default = { analyze(fn) {
968
976
  fnExtra.exprRoot = exprRoot.node.extra ??= {};
969
977
  fnExtra.name = node.id?.name || (isMarkoAttribute(markoRoot) ? markoRoot.node.default ? _marko_compiler.types.toIdentifier((markoRoot.parentPath.has("var") ? markoRoot.parentPath.get("var") : markoRoot.parentPath.get("name")).toString()) : markoRoot.node.name : _marko_compiler.types.isVariableDeclarator(fn.parent) && _marko_compiler.types.isIdentifier(fn.parent.id) ? fn.parent.id.name : _marko_compiler.types.isObjectMethod(node) && _marko_compiler.types.isIdentifier(node.key) ? node.key.name : "anonymous");
970
978
  reserveExportRegisterId(fnExtra, fn, markoRoot);
971
- if (isStaticRoot(markoRoot)) {
979
+ if (isStatic(markoRoot)) {
972
980
  const refs = getStaticDeclRefs(fn);
973
981
  if (refs.size) getReferencesByFn().set(fnExtra, refs);
974
982
  } else getReferencesByFn().set(fnExtra, /* @__PURE__ */ new Set([fnExtra.exprRoot]));
@@ -1047,7 +1055,7 @@ function registerImportedFn({ node, ...importedFn }) {
1047
1055
  (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
1048
1056
  }
1049
1057
  function reserveExportRegisterId(fnExtra, fn, markoRoot) {
1050
- if (!isStaticRoot(markoRoot)) return;
1058
+ if (!isStatic(markoRoot)) return;
1051
1059
  const exportNames = getExportNames(fn, markoRoot);
1052
1060
  const exportName = exportNames?.find((name) => _marko_compiler.types.isValidIdentifier(name));
1053
1061
  if (!exportName) return;
@@ -1105,7 +1113,7 @@ function addBindingRefs(binding, refs, seen) {
1105
1113
  const exprRoot = getExprRoot(ref);
1106
1114
  const markoRoot = getMarkoRoot(exprRoot);
1107
1115
  if (!markoRoot || canIgnoreRegister(markoRoot, exprRoot)) continue;
1108
- if (isStaticRoot(markoRoot)) getStaticDeclRefs(ref, refs, seen);
1116
+ if (isStatic(markoRoot)) getStaticDeclRefs(ref, refs, seen);
1109
1117
  else refs.add(exprRoot.node.extra ??= {});
1110
1118
  }
1111
1119
  }
@@ -1118,14 +1126,6 @@ function registerFunction(fnExtra) {
1118
1126
  function isMarkoAttribute(path) {
1119
1127
  return path ? path.isMarkoAttribute() : false;
1120
1128
  }
1121
- function isStaticRoot(path) {
1122
- switch (path.type) {
1123
- case "MarkoScriptlet": return path.node.static;
1124
- case "ExportDefaultDeclaration":
1125
- case "ExportNamedDeclaration": return true;
1126
- default: return false;
1127
- }
1128
- }
1129
1129
  //#endregion
1130
1130
  //#region src/translator/util/cyclic-memo.ts
1131
1131
  function createCyclicMemo(compute, cycleAnswer) {
@@ -1680,6 +1680,7 @@ const pureDOMFunctions = /* @__PURE__ */ new Set([
1680
1680
  "_const",
1681
1681
  "_load_signal",
1682
1682
  "_load_setup",
1683
+ "_load_setup_var",
1683
1684
  "_load_template",
1684
1685
  "_load_visible_trigger",
1685
1686
  "_load_event_trigger",
@@ -1749,7 +1750,8 @@ function getHTMLRuntime() {
1749
1750
  _attr_class,
1750
1751
  _attr_style,
1751
1752
  _escape_script,
1752
- _escape_style
1753
+ _escape_style,
1754
+ escapeDoubleQuotedAttrValue
1753
1755
  };
1754
1756
  }
1755
1757
  function getRuntimePath(output) {
@@ -1966,6 +1968,7 @@ var accessor_prop_exports = /* @__PURE__ */ __exportAll({
1966
1968
  AbortScopes: () => "B",
1967
1969
  AwaitCounter: () => "O",
1968
1970
  BranchAccessor: () => "C",
1971
+ BranchRenders: () => "BR",
1969
1972
  BranchScopes: () => "D",
1970
1973
  CatchContent: () => "E",
1971
1974
  ClosestBranch: () => "F",
@@ -2224,7 +2227,7 @@ function getOrCreateHtmlLoadWrapped(readyId, originalIdentifier, filename, trigg
2224
2227
  markoOpts.linkAssets?.onAsset("load", filename, readyId);
2225
2228
  const wrappedName = generateUid(`${originalIdentifier.name ?? "tag"}_withLoadAssets`);
2226
2229
  loadWrapped.set(readyId, wrappedName);
2227
- (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, _marko_compiler.types.stringLiteral(readyId), triggers ? _marko_compiler.types.valueToNode(triggers) : void 0))])], true));
2230
+ (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));
2228
2231
  return wrappedName;
2229
2232
  }
2230
2233
  function trackImportedRegisteredFns(importDecl) {
@@ -2640,8 +2643,16 @@ function normalizeStringExpression(parts, useIife) {
2640
2643
  if (exprs.length === 1 && !curStr && !strs[0]) return exprs[0];
2641
2644
  strs.push(curStr);
2642
2645
  if (useIife) {
2643
- const params = exprs.map((_, i) => _marko_compiler.types.identifier(`_w${i}`));
2644
- const iife = _marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.templateLiteral(strs.map((raw) => _marko_compiler.types.templateElement({ raw: escapeTemplateRaw(raw) })), params)), exprs);
2646
+ const args = [];
2647
+ const params = [];
2648
+ const body = _marko_compiler.types.templateLiteral(strs.map((raw) => _marko_compiler.types.templateElement({ raw: escapeTemplateRaw(raw) })), exprs.map((expr) => {
2649
+ if (expr.type !== "Identifier") return expr;
2650
+ const param = _marko_compiler.types.identifier(`_w${params.length}`);
2651
+ params.push(param);
2652
+ args.push(expr);
2653
+ return param;
2654
+ }));
2655
+ const iife = _marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression(params, body), args);
2645
2656
  _marko_compiler.types.addComment(iife, "leading", "@__PURE__");
2646
2657
  return iife;
2647
2658
  }
@@ -2960,8 +2971,8 @@ function getDeclaredBindingExpression(binding, inPlace = false) {
2960
2971
  if (canonicalBinding.localOf) return getDeclaredBindingExpression(canonicalBinding.localOf, inPlace);
2961
2972
  const { aliasOf: aliased, property, declaredAlias } = canonicalBinding;
2962
2973
  if (binding.declared) return _marko_compiler.types.identifier(binding.name);
2963
- if (canonicalBinding.declared || canonicalBinding.excludeProperties !== void 0) return _marko_compiler.types.identifier(canonicalBinding.name);
2964
- if (declaredAlias && declaredAlias.excludeProperties === void 0 && !getNearestDeclared(canonicalBinding)) return _marko_compiler.types.identifier(declaredAlias.name);
2974
+ if (canonicalBinding.declared || isRest(canonicalBinding)) return _marko_compiler.types.identifier(canonicalBinding.name);
2975
+ if (declaredAlias && !isRest(declaredAlias) && !getNearestDeclared(canonicalBinding)) return _marko_compiler.types.identifier(declaredAlias.name);
2965
2976
  if (!aliased) return _marko_compiler.types.identifier(canonicalBinding.name);
2966
2977
  if (property !== void 0) {
2967
2978
  const alias = !getNearestDeclared(aliased) && aliased.declaredAlias;
@@ -3091,7 +3102,7 @@ function translateVar(tag, initialValue, kind = "const", statements) {
3091
3102
  if (binding.declared) {
3092
3103
  if (binding.section === section) allPruned = false;
3093
3104
  else translateAliasInSection(tag, id, binding, kind);
3094
- } else if (binding.excludeProperties !== void 0) translateRest(tag, id, binding, kind);
3105
+ } else if (isRest(binding)) translateRest(tag, id, binding, kind);
3095
3106
  });
3096
3107
  if (allPruned) return;
3097
3108
  removeUndeclared(tagVar, section);
@@ -3108,7 +3119,7 @@ function translateVar(tag, initialValue, kind = "const", statements) {
3108
3119
  const changeBinding = binding.aliasOf.propertyAliases.get(changeName);
3109
3120
  if (changeBinding && changeName !== changeBinding.name) {
3110
3121
  const pattern = getDestructurePattern(id);
3111
- if (pattern) pattern.unshiftContainer("properties", _marko_compiler.types.objectProperty(_marko_compiler.types.identifier(changeName), _marko_compiler.types.identifier(changeBinding.name)));
3122
+ if (pattern) pattern.unshiftContainer("properties", _marko_compiler.types.objectProperty(toPropertyName(changeName), _marko_compiler.types.identifier(changeBinding.name)));
3112
3123
  }
3113
3124
  }
3114
3125
  });
@@ -3159,11 +3170,11 @@ function translateRest(tag, id, rest, kind) {
3159
3170
  }
3160
3171
  function getRestPattern(rest, id, from, shorthand) {
3161
3172
  const restElement = _marko_compiler.types.restElement(id);
3162
- if (rest.restOffset) return _marko_compiler.types.arrayPattern([...new Array(rest.restOffset - (from.restOffset || 0)).fill(null), restElement]);
3173
+ if (rest.restOffset !== void 0) return _marko_compiler.types.arrayPattern([...new Array(rest.restOffset - (from.restOffset || 0)).fill(null), restElement]);
3163
3174
  return _marko_compiler.types.objectPattern([...toArray(rest.excludeProperties, shorthand ? (name) => name === id.name ? toExcludedProperty(name) : toShorthandExcludedProperty(name) : toExcludedProperty), restElement]);
3164
3175
  }
3165
3176
  function withRestFallback(rest, from, value) {
3166
- return from.nullable ? _marko_compiler.types.logicalExpression("||", value, rest.restOffset ? _marko_compiler.types.arrayExpression([]) : _marko_compiler.types.objectExpression([])) : value;
3177
+ return from.nullable ? _marko_compiler.types.logicalExpression("||", value, rest.restOffset !== void 0 ? _marko_compiler.types.arrayExpression([]) : _marko_compiler.types.objectExpression([])) : value;
3167
3178
  }
3168
3179
  function getSectionTarget(tag, section) {
3169
3180
  let target = tag;
@@ -3376,7 +3387,7 @@ function getSignalFn(signal) {
3376
3387
  const aliasSignal = getSignal(alias.section, alias);
3377
3388
  if (signalHasStatements(aliasSignal)) {
3378
3389
  signal.forwards = push(signal.forwards, aliasSignal);
3379
- if (alias.excludeProperties !== void 0) {
3390
+ if (isRest(alias)) {
3380
3391
  const aliasId = _marko_compiler.types.identifier(alias.name);
3381
3392
  signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3382
3393
  scopeIdentifier,
@@ -3912,6 +3923,52 @@ function isOnlyChild(tag) {
3912
3923
  return true;
3913
3924
  }
3914
3925
  //#endregion
3926
+ //#region src/translator/util/module-read.ts
3927
+ const styleImportReg = /\.(?:css(?:\.[cm]?[jt]s)?|less|s[ac]ss|styl(?:us)?|pcss|postcss)(?:\?|$)/i;
3928
+ const kModuleRead = Symbol("module read");
3929
+ /** The module read an expression is, resolved on first use: translate replaces
3930
+ * a `<style/name>` tag. */
3931
+ function getModuleRead(path, expr) {
3932
+ return ((expr.extra ??= {})[kModuleRead] ??= resolveModuleRead(path, expr)) || void 0;
3933
+ }
3934
+ /** A module read of a stylesheet module, whose reads are class name strings. */
3935
+ function getStyleImportRead(path, expr) {
3936
+ const moduleRead = getModuleRead(path, expr);
3937
+ if (moduleRead && (moduleRead.request === void 0 || styleImportReg.test(moduleRead.request))) return moduleRead.read;
3938
+ }
3939
+ function toModuleReadExpression([name, ...members]) {
3940
+ let expr = _marko_compiler.types.identifier(name);
3941
+ for (const member of members) expr = _marko_compiler.types.memberExpression(expr, _marko_compiler.types.identifier(member));
3942
+ return expr;
3943
+ }
3944
+ function resolveModuleRead(path, expr) {
3945
+ switch (expr.type) {
3946
+ case "Identifier": {
3947
+ const decl = path.scope.getBinding(expr.name)?.path;
3948
+ const importDecl = decl?.parentPath;
3949
+ if (importDecl?.isImportDeclaration()) {
3950
+ const scriptlet = importDecl.parentPath;
3951
+ return scriptlet.isMarkoScriptlet() && scriptlet.node.target ? null : {
3952
+ read: [expr.name],
3953
+ request: importDecl.node.source.value
3954
+ };
3955
+ }
3956
+ return decl && isCoreTagName(decl, "style") && decl.node.var.type === "Identifier" ? {
3957
+ read: [expr.name],
3958
+ request: void 0
3959
+ } : null;
3960
+ }
3961
+ case "MemberExpression": {
3962
+ const object = !expr.computed && getModuleRead(path, expr.object);
3963
+ return object ? {
3964
+ read: [...object.read, expr.property.name],
3965
+ request: object.request
3966
+ } : null;
3967
+ }
3968
+ }
3969
+ return null;
3970
+ }
3971
+ //#endregion
3915
3972
  //#region src/translator/util/structure.ts
3916
3973
  const walkCodeToName = {
3917
3974
  [32]: "get",
@@ -3958,6 +4015,12 @@ function writeTo(path) {
3958
4015
  }
3959
4016
  };
3960
4017
  }
4018
+ function writeModuleReadTo(path, read) {
4019
+ getSection(path).structure?.push({
4020
+ kind: ModuleRead,
4021
+ read
4022
+ });
4023
+ }
3961
4024
  function writeTextTo(path, value) {
3962
4025
  if (value) getSection(path).structure?.push({
3963
4026
  kind: Text,
@@ -4018,6 +4081,10 @@ function resolveStructure(section) {
4018
4081
  appendLiteral(resolved.writes, op.value);
4019
4082
  textEdge = "own";
4020
4083
  break;
4084
+ case ModuleRead:
4085
+ resolved.writes.push(toModuleReadExpression(op.read), "");
4086
+ textEdge = void 0;
4087
+ break;
4021
4088
  case Node: {
4022
4089
  if (!op.binding) continue;
4023
4090
  const withVar = hasScopeOffset(op.binding);
@@ -4266,11 +4333,6 @@ function assertSetupWorkFound(program, section, written) {
4266
4333
  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.");
4267
4334
  }
4268
4335
  //#endregion
4269
- //#region src/translator/util/is-static.ts
4270
- function isStatic(path) {
4271
- return path.isImportDeclaration() || path.isExportDeclaration() || path.isMarkoScriptlet({ static: true });
4272
- }
4273
- //#endregion
4274
4336
  //#region src/translator/visitors/program/html.ts
4275
4337
  function getTemplateContentName() {
4276
4338
  return getSharedUid("content");
@@ -4758,7 +4820,7 @@ var custom_tag_default = {
4758
4820
  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>\`.`);
4759
4821
  if (childExtra.page) programExtra.page ??= true;
4760
4822
  if (tagExtra.tagNameLoad) tagExtra[kLoadTagBinding] = createBinding("#text", 0, getOrCreateSection(tag));
4761
- knownTagAnalyze(tag, childSection, programSection === childSection ? programSection.params && getBindingPropTree(programSection.params) : childExtra.paramsTree);
4823
+ knownTagAnalyze(tag, childSection, childExtra.paramsTree);
4762
4824
  const tagName = getStaticTagName(tag.node);
4763
4825
  if (tagExtra.tagNameLoad) {
4764
4826
  marker(tag, tagExtra[kLoadTagBinding]);
@@ -4804,6 +4866,7 @@ function translateDOM$1(tag) {
4804
4866
  const isLoad = !!loadConfig;
4805
4867
  const tagName = getStaticTagName(node);
4806
4868
  if (isLoad) {
4869
+ if (node.var) importRuntimeFeature("dynamic-tag-var");
4807
4870
  const childFileName = childFile.opts.filename;
4808
4871
  const { triggers, signals, setups } = getLoadIdentifiers();
4809
4872
  let triggerIdent = triggers.get(loadConfig);
@@ -4826,14 +4889,14 @@ function translateDOM$1(tag) {
4826
4889
  }
4827
4890
  return signalIdent;
4828
4891
  }, (section, childBinding) => {
4829
- const setupKey = `${triggerIdent ? triggerIdent.name : ""}\0${childFileName}`;
4892
+ const setupKey = `${triggerIdent ? triggerIdent.name : ""}\0${childFileName}${node.var ? "\0var" : ""}`;
4830
4893
  let setupIdent = setups.get(setupKey);
4831
4894
  if (!setupIdent) {
4832
4895
  setupIdent = generateUidIdentifier(`load_${tagName}_setup`);
4833
4896
  setups.set(setupKey, setupIdent);
4834
4897
  const setupLoadExpr = _marko_compiler.types.arrowFunctionExpression([], dynamicImport(buildLoadSetupVirtualModule(file, childFileName, childExports)));
4835
4898
  importRuntimeFeature("catch");
4836
- (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))]));
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))]));
4837
4900
  }
4838
4901
  addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(setupIdent, [
4839
4902
  scopeIdentifier,
@@ -5236,6 +5299,7 @@ var program_default = {
5236
5299
  },
5237
5300
  exit(program) {
5238
5301
  if (hasAnalyzeErrors()) return;
5302
+ analyzeRecursiveTags();
5239
5303
  finalizeReferences();
5240
5304
  const programExtra = program.node.extra;
5241
5305
  const paramsBinding = programExtra.binding;
@@ -5786,33 +5850,51 @@ const [getKnownTags] = createSectionState("known tags", () => []);
5786
5850
  const kContentSection = Symbol("known tag content section");
5787
5851
  const kPropTree = Symbol("known tag prop tree");
5788
5852
  const kKnownExprs = Symbol("known tag exprs");
5789
- function knownTagAnalyze(tag, contentSection, propTree) {
5853
+ const [getRecursiveTags] = createProgramState(() => []);
5854
+ function knownTagAnalyze(tag, contentSection, childParamsTree) {
5790
5855
  analyzeAttributeTags(tag);
5791
5856
  const section = getOrCreateSection(tag);
5792
5857
  const tagBody = tag.get("body");
5793
5858
  const tagExtra = tag.node.extra ??= {};
5794
- const childScopeBinding = tagExtra.nodeBinding = createBinding("#childScope", 0, section);
5795
- const attrExprs = /* @__PURE__ */ new Set([tagExtra]);
5859
+ tagExtra.nodeBinding = createBinding("#childScope", 0, section);
5796
5860
  startSection(tagBody);
5797
5861
  trackParamsReferences(tagBody, 2);
5798
5862
  getKnownTags(section).push(tagExtra);
5799
5863
  tagExtra[kContentSection] = contentSection;
5800
- tagExtra[kPropTree] = propTree;
5801
- if (contentSection.program === section.program) contentSection.callSections = sectionUtil.add(contentSection.callSections, section);
5802
5864
  const varBinding = trackVarReferences(tag, 4);
5803
- const exprs = tagExtra[kKnownExprs] = analyzeParams(tagExtra, section, tag, propTree, attrExprs);
5804
- setTagDerivedFrom(tag, propTree?.props?.[0]?.binding, exprs);
5865
+ const recursive = isSameOrChildSection(contentSection, section);
5866
+ let exprs;
5867
+ if (contentSection.program === section.program) {
5868
+ contentSection.callSections = sectionUtil.add(contentSection.callSections, section);
5869
+ if (recursive) getRecursiveTags().push(tag);
5870
+ else exprs = analyzeKnownTagParams(tag, getParamsTree(contentSection));
5871
+ } else exprs = analyzeKnownTagParams(tag, childParamsTree);
5805
5872
  if (varBinding) {
5806
5873
  addSetupExpr(section);
5807
5874
  const mutatesTagVar = !!(tag.node.var.type === "Identifier" && tag.scope.getBinding(tag.node.var.name)?.constantViolations.length);
5808
- const varExpr = isSameOrChildSection(contentSection, section) || (tagExtra.defineBodySection ? contentSection.returnValueExpr : mapParamReasonToExpr(exprs, getReturnParams(contentSection)));
5875
+ const varExpr = recursive || (tagExtra.defineBodySection ? contentSection.returnValueExpr : mapParamReasonToExpr(exprs, getReturnParams(contentSection)));
5876
+ const childScopeBinding = tagExtra.nodeBinding;
5809
5877
  varBinding.returnedBy = childScopeBinding;
5810
5878
  reserveId(childScopeBinding, 1);
5811
5879
  setDerivedFrom(varBinding, varExpr);
5812
5880
  if (mutatesTagVar || varExpr === true) addReason(getSlot(childScopeBinding), ALWAYS);
5813
5881
  if (varExpr !== true) addReasonExprs(getSlot(childScopeBinding), varExpr);
5814
5882
  }
5815
- addReasonExprs(getSlot(childScopeBinding), fromIter(attrExprs));
5883
+ }
5884
+ function analyzeRecursiveTags() {
5885
+ for (const tag of getRecursiveTags()) analyzeKnownTagParams(tag, getParamsTree(tag.node.extra[kContentSection]));
5886
+ }
5887
+ function getParamsTree(contentSection) {
5888
+ return contentSection.params && getBindingPropTree(contentSection.params, true);
5889
+ }
5890
+ function analyzeKnownTagParams(tag, propTree) {
5891
+ const tagExtra = tag.node.extra;
5892
+ const attrExprs = /* @__PURE__ */ new Set([tagExtra]);
5893
+ tagExtra[kPropTree] = propTree;
5894
+ const exprs = tagExtra[kKnownExprs] = analyzeParams(tagExtra, getSection(tag), tag, propTree, attrExprs);
5895
+ setTagDerivedFrom(tag, propTree?.props?.[0]?.binding, exprs);
5896
+ addReasonExprs(getSlot(tagExtra.nodeBinding), fromIter(attrExprs));
5897
+ return exprs;
5816
5898
  }
5817
5899
  function getReturnParams(section) {
5818
5900
  const sources = section.returnValueExpr && getSourcesForExpr(section.returnValueExpr);
@@ -6609,19 +6691,23 @@ function addValueReferences(refs, expr) {
6609
6691
  return isReferencedExtra(getCanonicalExtra(expr)) && !expr.initialValue ? bindingUtil.union(refs, getReferencedBindings(expr)) : refs;
6610
6692
  }
6611
6693
  function getWalkedBinding(op) {
6612
- return typeof op === "object" && op.kind !== "text" ? op.binding : void 0;
6694
+ return typeof op === "object" && (op.kind === "node" || op.kind === "child") ? op.binding : void 0;
6613
6695
  }
6614
6696
  function getLastOwnSourceReturn(intersection, section) {
6615
- let returnedBy;
6616
- for (const binding of intersection) if (binding.section === section && binding.sources) {
6617
- returnedBy = reduce(binding.sources.state, lastReturnedBy, returnedBy);
6618
- returnedBy = reduce(binding.sources.param, lastReturnedBy, returnedBy);
6619
- }
6620
- return returnedBy;
6621
- }
6622
- function lastReturnedBy(last, source) {
6623
- const { returnedBy } = source;
6624
- return returnedBy && (!last || last.id < returnedBy.id) ? returnedBy : last;
6697
+ let last;
6698
+ const seen = /* @__PURE__ */ new Set();
6699
+ const track = (binding) => {
6700
+ if (binding.section === section && !seen.has(binding)) {
6701
+ seen.add(binding);
6702
+ const { returnedBy } = getAliasRoot(binding) || binding;
6703
+ if (returnedBy && (!last || last.id < returnedBy.id)) last = returnedBy;
6704
+ if (binding.derivedFrom) forEach(getValueReferences(binding.derivedFrom), track);
6705
+ forEach(binding.sources?.state, track);
6706
+ forEach(binding.sources?.param, track);
6707
+ }
6708
+ };
6709
+ forEach(intersection, track);
6710
+ return last;
6625
6711
  }
6626
6712
  function getIntersectionSource(intersection, section, resolved) {
6627
6713
  if (!resolved.has(intersection)) {
@@ -6665,11 +6751,6 @@ function resolveBindingSources(binding) {
6665
6751
  binding.sources = globalSources;
6666
6752
  return;
6667
6753
  }
6668
- if (binding.localOf) {
6669
- resolveBindingSources(binding.localOf);
6670
- binding.sources = binding.localOf.sources;
6671
- return;
6672
- }
6673
6754
  const aliasRoot = getAliasRoot(binding);
6674
6755
  if (aliasRoot) {
6675
6756
  if (!resolvedSources.has(aliasRoot)) {
@@ -6715,18 +6796,20 @@ function pruneBinding(binding) {
6715
6796
  binding.pruned = false;
6716
6797
  for (const read of binding.reads.keys()) if (isDroppableValue(read)) forEach(read.derives, pruneBinding);
6717
6798
  forEach(binding.assignments, pruneWriter);
6799
+ const assignedObject = getAssignedObject(binding);
6718
6800
  for (const [expr, reads] of binding.reads) {
6719
- const owner = getReadOwner(binding.aliasOf, expr);
6801
+ const owner = assignedObject ? getReadOwner(assignedObject, expr) || assignedObject : getReadOwner(binding.aliasOf, expr);
6720
6802
  if (owner) {
6721
6803
  owner.reads.set(expr, concat(owner.reads.get(expr), reads));
6722
6804
  binding.reads.delete(expr);
6723
6805
  }
6724
6806
  }
6725
- let shouldPrune = !binding.reads.size && !(binding.reserveSize && some(binding.assignments, inEmittedExpr));
6807
+ let shouldPrune = true;
6726
6808
  for (const alias of binding.aliases) if (pruneBinding(alias)) binding.aliases.delete(alias);
6727
6809
  else if (alias.type !== 5) shouldPrune = false;
6728
6810
  for (const [key, alias] of binding.propertyAliases) if (pruneBinding(alias)) binding.propertyAliases.delete(key);
6729
6811
  else if (alias.type !== 5) shouldPrune = false;
6812
+ shouldPrune &&= !binding.reads.size && !(binding.reserveSize && some(binding.assignments, inEmittedExpr));
6730
6813
  binding.pruned = shouldPrune;
6731
6814
  if (shouldPrune && !hasEmittedAssignment(binding)) {
6732
6815
  if (binding.derivedFrom) forEach(binding.derivedFrom, dropUnreadValue);
@@ -7441,7 +7524,7 @@ function getOrCreateLocalClosure(local, section) {
7441
7524
  while (section.parent !== local.section) section = section.parent;
7442
7525
  let closure = local.localClosures?.get(section);
7443
7526
  if (!closure) {
7444
- closure = createBinding(local.name, 4, section, void 0, void 0, void 0, local.loc);
7527
+ closure = createBinding(local.name, 2, section, void 0, void 0, void 0, local.loc);
7445
7528
  closure.localOf = local;
7446
7529
  (local.localClosures ??= /* @__PURE__ */ new Map()).set(section, closure);
7447
7530
  }
@@ -7462,6 +7545,7 @@ function trackDomVarReferences(tag, binding) {
7462
7545
  binding.originalName = tagVar.name;
7463
7546
  if (babelBinding.constantViolations.length) for (const ref of babelBinding.constantViolations) throw ref.type === "MarkoTag" ? ref.get("var").buildCodeFrameError(`Duplicate declaration of \`${binding.originalName}\`.`) : ref.buildCodeFrameError(`\`${binding.originalName}\` is a [tag variable](https://markojs.com/docs/reference/language#tag-variables) on a native element (an element reference) and cannot be assigned to.`);
7464
7547
  for (const ref of babelBinding.referencePaths) {
7548
+ assertReferencedInRender(ref, tagVar.name);
7465
7549
  const refSection = getOrCreateSection(ref);
7466
7550
  const invoked = isInvokedFunction(ref);
7467
7551
  const hoisted = isReferenceHoisted(babelBinding.path, ref) ? getCommonSection(refSection, binding.section) : false;
@@ -7485,7 +7569,7 @@ function trackVarReferences(tag, type, aliased) {
7485
7569
  let target = aliased && getCanonicalBinding(aliased);
7486
7570
  if (target) {
7487
7571
  const { excludeProperties, restOffset } = target;
7488
- if (excludeProperties !== void 0) target = target.aliasOf;
7572
+ if (isRest(target)) target = target.aliasOf;
7489
7573
  createBindingsAndTrackReferences(tagVar, target.type, tag.scope, section, target, void 0, excludeProperties, restOffset, false);
7490
7574
  return target;
7491
7575
  }
@@ -7503,6 +7587,7 @@ function trackParamsReferences(body, type) {
7503
7587
  if (bodySection) bodySection.params = paramsBinding;
7504
7588
  for (let i = 0; i < params.length; i++) {
7505
7589
  const param = params[i];
7590
+ if (param.type === "RestElement") assertRestNotAssigned(body.scope, param.argument);
7506
7591
  if (i === 0 && param.type === "RestElement" && param.argument.type === "Identifier") {
7507
7592
  const { argument } = param;
7508
7593
  paramsBinding.name = argument.name;
@@ -7544,9 +7629,10 @@ function isReferenceHoisted(bindingPath, reference) {
7544
7629
  function trackReferencesForBinding(babelBinding, binding) {
7545
7630
  const { referencePaths, constantViolations } = babelBinding;
7546
7631
  for (const ref of referencePaths) {
7547
- const refSection = getOrCreateSection(ref);
7548
7632
  const markoRoot = getMarkoRoot(ref);
7549
- if (!binding.declared && binding.excludeProperties === void 0) {
7633
+ assertReferencedInRender(ref, ref.node.name, markoRoot);
7634
+ const refSection = getOrCreateSection(ref);
7635
+ if (!binding.declared && !isRest(binding)) {
7550
7636
  const root = getNearestDeclared(binding);
7551
7637
  binding.declared = !!root && ref.scope.getBinding(root.name) !== babelBinding.scope.getBinding(root.name);
7552
7638
  }
@@ -7573,6 +7659,7 @@ function trackReferencesForBinding(babelBinding, binding) {
7573
7659
  }
7574
7660
  for (const ref of constantViolations) {
7575
7661
  if (ref.type === "MarkoTag") throw ref.get("var").buildCodeFrameError(`Duplicate declaration of \`${binding.name}\`.`);
7662
+ assertReferencedInRender(ref, binding.name);
7576
7663
  if (isReferenceHoisted(babelBinding.path, ref)) throw ref.buildCodeFrameError(`\`${binding.name}\` is declared by a tag below this assignment; a [tag variable](https://markojs.com/docs/reference/language#tag-variables) can only be assigned below its declaration. Move the declaring tag above this code.`);
7577
7664
  if (ref.isUpdateExpression()) trackAssignment(ref.get("argument"), binding);
7578
7665
  else if (ref.isAssignmentExpression()) {
@@ -7588,6 +7675,8 @@ function trackAssignment(assignment, binding) {
7588
7675
  const fnParent = getFnParent(assignment);
7589
7676
  if (!fnParent) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag ${binding.type === 2 ? "parameter" : "variable"} and can only be assigned within a script or function.`);
7590
7677
  if (binding.type === 3) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag parameter and cannot be assigned to.`);
7678
+ let assigned = binding;
7679
+ while (isDirectAlias(assigned)) assigned = assigned.aliasOf;
7591
7680
  const fnRoot = getFnRoot(fnParent);
7592
7681
  const fnExtra = fnRoot && (fnRoot.node.extra ??= {});
7593
7682
  const section = getOrCreateSection(assignment);
@@ -7595,7 +7684,7 @@ function trackAssignment(assignment, binding) {
7595
7684
  forEachIdentifierPath(assignment, (id) => {
7596
7685
  if (id.node.name === binding.name) {
7597
7686
  const idExtra = id.node.extra ??= {};
7598
- idExtra.assignment = binding;
7687
+ idExtra.assignment = assigned;
7599
7688
  idExtra.section = section;
7600
7689
  idExtra.exprRoot = getExprRoot(fnRoot || assignment).node.extra ??= {};
7601
7690
  idExtra.fnRoot = fnExtra;
@@ -7604,16 +7693,19 @@ function trackAssignment(assignment, binding) {
7604
7693
  fnExtra.section = section;
7605
7694
  fnExtra.exprRoot = idExtra.exprRoot;
7606
7695
  }
7607
- if (binding.aliasOf && binding.property !== void 0) {
7608
- if (binding.aliasOf === binding.section.params) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag parameter and cannot be assigned to.`);
7609
- const changePropName = binding.property + "Change";
7610
- const changeBinding = binding.aliasOf.propertyAliases.get(changePropName) || createBinding(generateUid(changePropName), binding.type, binding.section, binding.aliasOf, changePropName, void 0, id.node.loc, binding.declared);
7696
+ if (assigned.aliasOf && assigned.property !== void 0) {
7697
+ if (assigned.aliasOf === assigned.section.params) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag parameter and cannot be assigned to.`);
7698
+ const changePropName = assigned.property + "Change";
7699
+ const changeBinding = assigned.aliasOf.propertyAliases.get(changePropName) || createBinding(generateUid(changePropName), assigned.type, assigned.section, assigned.aliasOf, changePropName, void 0, id.node.loc, assigned.declared);
7611
7700
  idExtra.assignmentTo = changeBinding;
7612
7701
  addReadToExpression(id, changeBinding, void 0);
7613
7702
  }
7614
7703
  }
7615
7704
  });
7616
7705
  }
7706
+ function assertReferencedInRender(ref, name, markoRoot = getMarkoRoot(ref)) {
7707
+ if (markoRoot && isStatic(markoRoot)) throw ref.buildCodeFrameError(`\`${name}\` exists only while the template renders, so module level code ([\`static\`, \`server\` and \`client\`](https://markojs.com/docs/reference/language#static) and [\`export\`](https://markojs.com/docs/reference/language#export) statements), which runs once as the template loads, cannot reference it. Reference it in the template instead, passing it to module level functions as an argument.`);
7708
+ }
7617
7709
  function setReferencesScope(path) {
7618
7710
  const fnRoot = getFnRoot(path);
7619
7711
  if (fnRoot) (fnRoot.node.extra ??= {}).referencesScope = true;
@@ -7628,8 +7720,7 @@ function createBindingsAndTrackReferences(lVal, type, scope, section, aliased, p
7628
7720
  createBindingsAndTrackReferences(lVal.left, type, scope, section, aliased, property, excludeProperties, restOffset, declared);
7629
7721
  break;
7630
7722
  case "Identifier": {
7631
- const binding = (lVal.extra ??= {}).binding = createBinding(lVal.name, type, section, aliased, property, excludeProperties, lVal.loc, declared);
7632
- if (restOffset) binding.restOffset = restOffset;
7723
+ const binding = (lVal.extra ??= {}).binding = createBinding(lVal.name, type, section, aliased, property, excludeProperties, lVal.loc, declared, restOffset);
7633
7724
  trackReferencesForBinding(scope.getBinding(lVal.name), binding);
7634
7725
  break;
7635
7726
  }
@@ -7639,8 +7730,10 @@ function createBindingsAndTrackReferences(lVal, type, scope, section, aliased, p
7639
7730
  const { properties } = lVal;
7640
7731
  const hasRest = properties.length > 0 && properties[properties.length - 1].type === "RestElement";
7641
7732
  const declaresPattern = declared || hasRest;
7642
- for (const prop of lVal.properties) if (prop.type === "RestElement") createBindingsAndTrackReferences(prop.argument, type, scope, section, patternBinding, void 0, excludeProperties, void 0, declaresPattern);
7643
- else {
7733
+ for (const prop of lVal.properties) if (prop.type === "RestElement") {
7734
+ assertRestNotAssigned(scope, prop.argument);
7735
+ createBindingsAndTrackReferences(prop.argument, type, scope, section, patternBinding, void 0, excludeProperties, void 0, declaresPattern);
7736
+ } else {
7644
7737
  let key;
7645
7738
  if (!prop.computed && prop.key.type === "Identifier") key = prop.key.name;
7646
7739
  else if (prop.key.type === "StringLiteral") key = prop.key.value;
@@ -7660,6 +7753,7 @@ function createBindingsAndTrackReferences(lVal, type, scope, section, aliased, p
7660
7753
  index++;
7661
7754
  if (element) {
7662
7755
  if (element.type === "RestElement") {
7756
+ assertRestNotAssigned(scope, element.argument);
7663
7757
  excludeProperties = index > 0 ? addNumericPropertiesUntil(excludeProperties, index) : void 0;
7664
7758
  createBindingsAndTrackReferences(element.argument, type, scope, section, patternBinding, void 0, excludeProperties, index, declaresPattern);
7665
7759
  } else if (_marko_compiler.types.isLVal(element)) {
@@ -7678,16 +7772,29 @@ function createBindingsAndTrackReferences(lVal, type, scope, section, aliased, p
7678
7772
  function isAssignment(ref) {
7679
7773
  return ref.type !== "MarkoTag";
7680
7774
  }
7775
+ function assertRestNotAssigned(scope, rest) {
7776
+ if (rest.type === "Identifier") {
7777
+ const assignment = scope.getBinding(rest.name).constantViolations.find(isAssignment);
7778
+ if (assignment) throw assignment.buildCodeFrameError(`\`${rest.name}\` is a rest element, which has no [change handler](https://markojs.com/docs/reference/language#shorthand-change-handlers-two-way-binding) to receive a new value, so it cannot be assigned to. Assign the properties of the value it is destructured from instead.`);
7779
+ }
7780
+ }
7681
7781
  function trackReference(referencePath, binding) {
7682
7782
  let root = referencePath;
7683
7783
  let reference = binding;
7684
7784
  while (true) {
7685
7785
  const { parent } = root;
7686
- if (!_marko_compiler.types.isMemberExpression(parent) && !_marko_compiler.types.isOptionalMemberExpression(parent) || isWrittenMember(root.parentPath)) break;
7786
+ if (!_marko_compiler.types.isMemberExpression(parent) && !_marko_compiler.types.isOptionalMemberExpression(parent)) break;
7687
7787
  let prop = getMemberExpressionPropString(parent);
7788
+ if (isAssignedMember(root.parentPath)) {
7789
+ let object = reference;
7790
+ while (isDirectAlias(object)) object = object.aliasOf;
7791
+ if (isRest(object)) throw root.parentPath.buildCodeFrameError(`\`${referencePath.node.name}\` is a rest element, a copy rebuilt from the value it is destructured from whenever that changes, so assigning its members would be lost. Assign the property on that value instead, or keep your own copy in a \`<let>\`.`);
7792
+ addAssignedProperty(object, prop);
7793
+ break;
7794
+ }
7688
7795
  if (prop === void 0) break;
7689
- if (reference.aliasOf && reference.excludeProperties !== void 0) {
7690
- if (reference.restOffset) {
7796
+ if (reference.aliasOf && isRest(reference)) {
7797
+ if (reference.restOffset !== void 0) {
7691
7798
  if (isIndexProperty(prop)) {
7692
7799
  prop = `${+prop + reference.restOffset}`;
7693
7800
  reference = reference.aliasOf;
@@ -7702,7 +7809,7 @@ function trackReference(referencePath, binding) {
7702
7809
  (referencePath.node.extra ??= {}).binding = binding;
7703
7810
  addReadToExpression(root, reference, void 0);
7704
7811
  }
7705
- function isWrittenMember(member) {
7812
+ function isAssignedMember(member) {
7706
7813
  const { node, parent } = member;
7707
7814
  switch (parent.type) {
7708
7815
  case "AssignmentExpression":
@@ -7830,7 +7937,9 @@ function untrackExtra(exprExtra) {
7830
7937
  if (reads) {
7831
7938
  readsByExpr.delete(exprExtra);
7832
7939
  getFunctionReadsByExpression().delete(exprExtra);
7833
- forEach(reads, (read) => read.binding.reads.delete(exprExtra));
7940
+ forEach(reads, (read) => {
7941
+ for (let cur = read.binding; cur; cur = cur.aliasOf) cur.reads.delete(exprExtra);
7942
+ });
7834
7943
  }
7835
7944
  }
7836
7945
  function dropContent(body) {
@@ -7990,7 +8099,7 @@ function getKnownExprsAt(exprs, binding) {
7990
8099
  //#region src/translator/util/bindings.ts
7991
8100
  const [getBindings] = createProgramState(() => /* @__PURE__ */ new Set());
7992
8101
  const [getNextBindingId, setNextBindingId] = createProgramState(() => 0);
7993
- function createBinding(name, type, refSection, aliased, property, excludeProperties, loc = null, refDeclared = false) {
8102
+ function createBinding(name, type, refSection, aliased, property, excludeProperties, loc = null, refDeclared = false, restOffset) {
7994
8103
  const id = getNextBindingId();
7995
8104
  const section = aliased ? aliased.section : refSection;
7996
8105
  const sameSection = refSection === section;
@@ -8009,6 +8118,7 @@ function createBinding(name, type, refSection, aliased, property, excludePropert
8009
8118
  closureId: void 0,
8010
8119
  assignments: void 0,
8011
8120
  excludeProperties,
8121
+ assignedProperties: void 0,
8012
8122
  sources: void 0,
8013
8123
  intersection: void 0,
8014
8124
  derivedFrom: void 0,
@@ -8022,11 +8132,11 @@ function createBinding(name, type, refSection, aliased, property, excludePropert
8022
8132
  declaredAlias: void 0,
8023
8133
  localOf: void 0,
8024
8134
  localClosures: void 0,
8025
- restOffset: void 0,
8135
+ restOffset,
8026
8136
  returnedBy: void 0,
8027
8137
  reserveSize: 0,
8028
8138
  scopeAccessor: void 0,
8029
- nullable: !sameSection || excludeProperties === void 0,
8139
+ nullable: !sameSection || excludeProperties === void 0 && restOffset === void 0,
8030
8140
  pruned: void 0,
8031
8141
  exposed: false,
8032
8142
  hasLazyReads: false
@@ -8053,6 +8163,18 @@ function getOrCreatePropertyAlias(binding, property) {
8053
8163
  while (isDirectAlias(binding)) binding = binding.aliasOf;
8054
8164
  return binding.propertyAliases.get(property) || createBinding(`${binding.name}_${property.replace(/[^a-zA-Z0-9_$]/g, "_")}`, binding.type, binding.section, binding, property);
8055
8165
  }
8166
+ function addAssignedProperty(binding, property) {
8167
+ if (binding.assignedProperties !== true) binding.assignedProperties = property === void 0 || propsUtil.add(binding.assignedProperties, property);
8168
+ }
8169
+ function getAssignedObject(binding) {
8170
+ let object;
8171
+ for (let alias = binding; alias.aliasOf && !isRest(alias); alias = alias.aliasOf) if (alias.property !== void 0) {
8172
+ let parent = alias.aliasOf;
8173
+ while (isDirectAlias(parent)) parent = parent.aliasOf;
8174
+ if (parent.assignedProperties === true || propsUtil.has(parent.assignedProperties, alias.property)) object = alias.aliasOf;
8175
+ }
8176
+ return object;
8177
+ }
8056
8178
  function getPropertyAlias(binding, properties) {
8057
8179
  return reduce(properties, getExistingPropertyAlias, binding);
8058
8180
  }
@@ -8111,12 +8233,15 @@ function getNearestDeclared(binding) {
8111
8233
  for (let cur = binding; cur; cur = cur.aliasOf) if (cur.declared) return cur;
8112
8234
  }
8113
8235
  function isDirectAlias(binding) {
8114
- return binding.aliasOf !== void 0 && binding.property === void 0 && binding.excludeProperties === void 0;
8236
+ return binding.aliasOf !== void 0 && binding.property === void 0 && !isRest(binding);
8237
+ }
8238
+ function isRest(binding) {
8239
+ return binding.excludeProperties !== void 0 || binding.restOffset !== void 0;
8115
8240
  }
8116
8241
  function getDebugScopeAccess(binding) {
8117
8242
  let root = binding;
8118
8243
  let access = "";
8119
- while (!(root.loc || root.declared) && root.aliasOf && root.excludeProperties === void 0) {
8244
+ while (!(root.loc || root.declared) && root.aliasOf && !isRest(root)) {
8120
8245
  if (root.property !== void 0) access = toAccess(root.property) + access;
8121
8246
  root = root.aliasOf;
8122
8247
  }
@@ -8132,7 +8257,7 @@ function getDebugName(binding) {
8132
8257
  if (isTemplateParam(binding)) {
8133
8258
  let root = binding;
8134
8259
  let access = "";
8135
- while (root.aliasOf !== root.section.params && root.excludeProperties === void 0) {
8260
+ while (root.aliasOf !== root.section.params && !isRest(root)) {
8136
8261
  if (root.property !== void 0) access = toAccess(root.property) + access;
8137
8262
  root = root.aliasOf;
8138
8263
  }
@@ -8150,11 +8275,11 @@ function getDebugNamesAsIdentifier(refs) {
8150
8275
  function getDebugNameAsIdentifier(binding) {
8151
8276
  let root = binding;
8152
8277
  let access = "";
8153
- if (isTemplateParam(binding)) while (root.aliasOf !== root.section.params && root.excludeProperties === void 0) {
8278
+ if (isTemplateParam(binding)) while (root.aliasOf !== root.section.params && !isRest(root)) {
8154
8279
  if (root.property !== void 0) access = `_${root.property.replace(/[^a-z0-9_$]/gi, "_") + access}`;
8155
8280
  root = root.aliasOf;
8156
8281
  }
8157
- else while (!(root.loc || root.declared) && root.aliasOf && root.excludeProperties === void 0) {
8282
+ else while (!(root.loc || root.declared) && root.aliasOf && !isRest(root)) {
8158
8283
  if (root.property !== void 0) access = `_${root.property.replace(/[^a-z0-9_$]/gi, "_") + access}`;
8159
8284
  root = root.aliasOf;
8160
8285
  }
@@ -8164,7 +8289,7 @@ function isInvokeOnlyBinding(binding) {
8164
8289
  return !someAlias(binding, isReadBeyondInvoking, void 0);
8165
8290
  }
8166
8291
  function isReadBeyondInvoking(binding) {
8167
- if (binding.assignments || binding.hoists || binding.getters.size || binding.propertyAliases.size || binding.excludeProperties) return true;
8292
+ if (binding.assignments || binding.hoists || binding.getters.size || binding.propertyAliases.size || isRest(binding)) return true;
8168
8293
  for (const expr of binding.reads.keys()) if (!expr.invokeOnly) return true;
8169
8294
  return false;
8170
8295
  }
@@ -9878,9 +10003,11 @@ var referenced_identifier_default = {
9878
10003
  const { name } = identifier.node;
9879
10004
  if (identifier.scope.hasBinding(name)) return;
9880
10005
  if (name === "$global") {
10006
+ assertReferencedInRender(identifier, name);
9881
10007
  setReferencesScope(identifier);
9882
10008
  trackGlobalReference(identifier);
9883
10009
  } else if (name === "$signal") {
10010
+ assertReferencedInRender(identifier, name);
9884
10011
  const section = getOrCreateSection(identifier);
9885
10012
  section.hasAbortSignal = true;
9886
10013
  setReferencesScope(identifier);
@@ -10063,7 +10190,7 @@ var native_tag_default = {
10063
10190
  } else {
10064
10191
  assertValidNativeEventHandlerAttr(tag, attr);
10065
10192
  if (isChangeHandlerAttr) valueExtra.retained = true;
10066
- if (!evaluate(attr.value).confident) {
10193
+ if (!isStaticDelimitedAttr(tag, attr) && !evaluate(attr.value).confident) {
10067
10194
  hasDynamicAttributes = true;
10068
10195
  addSetupExpr(tagSection, attr.value);
10069
10196
  } else if (attr.name === "content" && tagName !== "meta") addSetupExpr(tagSection, attr.value);
@@ -10137,13 +10264,21 @@ var native_tag_default = {
10137
10264
  const { confident, computed } = evaluate(value);
10138
10265
  if (confident) write`${getStaticAttrMarkup(name, computed)}`;
10139
10266
  else if (name === "class" || name === "style") {
10140
- const meta = {
10141
- staticItems: void 0,
10142
- dynamicItems: void 0,
10143
- dynamicValues: void 0
10144
- };
10145
- trackDelimitedAttrValue(value, meta);
10146
- if (!meta.dynamicItems && meta.staticItems) write`${getStaticAttrMarkup(name, meta.staticItems)}`;
10267
+ const meta = trackDelimitedAttrValue(tag, name, value);
10268
+ const { staticParts } = meta;
10269
+ if (getDelimitedAttrItems(name, meta) && staticParts.length) {
10270
+ if (staticParts.every(isLiteralPart)) write`${getStaticAttrMarkup(name, staticParts)}`;
10271
+ else {
10272
+ write` class="`;
10273
+ for (let i = 0; i < staticParts.length; i++) {
10274
+ const part = staticParts[i];
10275
+ if (i) write` `;
10276
+ if (isLiteralPart(part)) write`${getHTMLRuntime().escapeDoubleQuotedAttrValue(part)}`;
10277
+ else writeModuleReadTo(tag, part);
10278
+ }
10279
+ write`"`;
10280
+ }
10281
+ }
10147
10282
  }
10148
10283
  }
10149
10284
  write`>`;
@@ -10245,7 +10380,7 @@ var native_tag_default = {
10245
10380
  write`${callRuntime("_attr_option_value", value)}`;
10246
10381
  continue;
10247
10382
  }
10248
- write`${confident ? getStaticAttrMarkup(name, computed) : factorAttrConditional(buildAttrExpression(name, value))}`;
10383
+ write`${confident ? getStaticAttrMarkup(name, computed) : factorAttrConditional(buildAttrExpression(tag, name, value))}`;
10249
10384
  }
10250
10385
  if (handlers) for (const index of handlers) addHTMLEffectCall(tagSection, getReferencedBindings(attributes[index].value.extra));
10251
10386
  const isOpenOnly = !!(tagDef && tagDef.parseOptions?.openTagOnly);
@@ -10332,37 +10467,27 @@ var native_tag_default = {
10332
10467
  const valueReferences = getReferencedBindings(value.extra);
10333
10468
  switch (name) {
10334
10469
  case "class":
10335
- case "style": {
10336
- const helper = `_attr_${name}`;
10470
+ case "style":
10337
10471
  if (!confident) {
10338
- const nodeExpr = createScopeReadExpression(nodeBinding);
10339
- const meta = {
10340
- staticItems: void 0,
10341
- dynamicItems: void 0,
10342
- dynamicValues: void 0
10343
- };
10344
- let stmt;
10345
- trackDelimitedAttrValue(value, meta);
10346
- if (meta.dynamicItems) stmt = _marko_compiler.types.expressionStatement(callRuntime(helper, nodeExpr, value));
10347
- else if (meta.dynamicValues) {
10348
- const keys = Object.keys(meta.dynamicValues);
10349
- if (keys.length === 1) {
10350
- const [key] = keys;
10351
- const value = meta.dynamicValues[key];
10352
- stmt = _marko_compiler.types.expressionStatement(callRuntime(`_attr_${name}_item`, nodeExpr, _marko_compiler.types.stringLiteral(key), value));
10353
- } else {
10354
- const props = [];
10355
- for (const key of keys) {
10356
- const value = meta.dynamicValues[key];
10357
- props.push(_marko_compiler.types.objectProperty(toPropertyName(key), value));
10358
- }
10359
- stmt = _marko_compiler.types.expressionStatement(callRuntime(`_attr_${name}_items`, nodeExpr, _marko_compiler.types.objectExpression(props)));
10360
- }
10472
+ const meta = trackDelimitedAttrValue(tag, name, value);
10473
+ const items = getDelimitedAttrItems(name, meta);
10474
+ const calls = [];
10475
+ const assert = buildClassTogglesAssert(meta);
10476
+ if (assert) calls.push(assert);
10477
+ if (!items) calls.push(callRuntime(`_attr_${name}`, createScopeReadExpression(nodeBinding), value));
10478
+ else {
10479
+ const single = [];
10480
+ for (const { key, value } of items) if (isLiteralPart(key) && !/\s/.test(key)) single.push({
10481
+ key,
10482
+ value
10483
+ });
10484
+ else calls.push(callRuntime("_attr_class_names", createScopeReadExpression(nodeBinding), toClassPartExpression(key), value));
10485
+ if (single.length === 1) calls.push(callRuntime(`_attr_${name}_item`, createScopeReadExpression(nodeBinding), _marko_compiler.types.stringLiteral(single[0].key), single[0].value));
10486
+ else if (single.length) calls.push(callRuntime(`_attr_${name}_items`, createScopeReadExpression(nodeBinding), _marko_compiler.types.objectExpression(single.map(({ key, value }) => _marko_compiler.types.objectProperty(toPropertyName(key), value)))));
10361
10487
  }
10362
- if (stmt) addStatement("render", tagSection, valueReferences, stmt, true);
10488
+ for (const call of calls) addStatement("render", tagSection, valueReferences, _marko_compiler.types.expressionStatement(call), true);
10363
10489
  }
10364
10490
  break;
10365
- }
10366
10491
  default: if (confident) break;
10367
10492
  else addStatement("render", tagSection, valueReferences, _marko_compiler.types.expressionStatement(callRuntime("_attr", createScopeReadExpression(nodeBinding), _marko_compiler.types.stringLiteral(name), value)), true);
10368
10493
  }
@@ -10637,13 +10762,13 @@ function getStaticAttrMarkup(name, computed) {
10637
10762
  default: return getHTMLRuntime()._attr(name, computed);
10638
10763
  }
10639
10764
  }
10640
- function buildAttrExpression(name, value) {
10641
- if (value.type === "ConditionalExpression") return _marko_compiler.types.conditionalExpression(value.test, buildAttrExpression(name, value.consequent), buildAttrExpression(name, value.alternate));
10765
+ function buildAttrExpression(tag, name, value) {
10766
+ if (value.type === "ConditionalExpression") return _marko_compiler.types.conditionalExpression(value.test, buildAttrExpression(tag, name, value.consequent), buildAttrExpression(tag, name, value.alternate));
10642
10767
  const { confident, computed } = evaluate(value);
10643
10768
  if (confident) return _marko_compiler.types.stringLiteral(getStaticAttrMarkup(name, computed));
10644
10769
  switch (name) {
10645
- case "class": return buildStringAttrAnd(name, value) || buildClassAttrExpression(value) || callRuntime("_attr_class", value);
10646
- case "style": return buildStringAttrAnd(name, value) || callRuntime("_attr_style", value);
10770
+ case "class": return buildClassAttrExpression(tag, value) || callRuntime("_attr_class", value);
10771
+ case "style": return buildStyleAttrAnd(value) || callRuntime("_attr_style", value);
10647
10772
  default: return buildLogicalAttr(name, value) || callRuntime("_attr", _marko_compiler.types.stringLiteral(name), value);
10648
10773
  }
10649
10774
  }
@@ -10677,105 +10802,198 @@ function buildLogicalAttr(name, value) {
10677
10802
  const attr = getHTMLRuntime()._attr(name, computed);
10678
10803
  return callRuntime(value.operator === "&&" ? "_attr_and" : value.operator === "||" ? "_attr_or" : "_attr_nullish", _marko_compiler.types.stringLiteral(name), value.left, _marko_compiler.types.stringLiteral(attr));
10679
10804
  }
10680
- function buildStringAttrAnd(name, value) {
10805
+ function buildStyleAttrAnd(value) {
10681
10806
  if (value.type === "LogicalExpression" && value.operator === "&&") {
10682
10807
  const { confident, computed } = evaluate(value.right);
10683
- if (confident) return _marko_compiler.types.conditionalExpression(value.left, _marko_compiler.types.stringLiteral(getStaticAttrMarkup(name, computed)), _marko_compiler.types.stringLiteral(""));
10808
+ if (confident) return _marko_compiler.types.conditionalExpression(value.left, _marko_compiler.types.stringLiteral(getStaticAttrMarkup("style", computed)), _marko_compiler.types.stringLiteral(""));
10684
10809
  }
10685
10810
  }
10686
10811
  const MAX_PRECOMPUTED_CLASS_TOGGLES = 4;
10687
- function buildClassAttrExpression(value) {
10688
- if (value.type !== "ObjectExpression" && value.type !== "ArrayExpression") return;
10812
+ function buildClassAttrExpression(tag, value) {
10813
+ const meta = trackDelimitedAttrValue(tag, "class", value);
10814
+ if (meta.dynamic) return;
10815
+ const markup = buildClassMarkup(meta);
10816
+ const assert = markup && buildClassTogglesAssert(meta);
10817
+ return assert ? _marko_compiler.types.sequenceExpression([assert, markup]) : markup;
10818
+ }
10819
+ function buildClassMarkup({ staticParts, dynamicValues = [] }) {
10820
+ if (dynamicValues.length > MAX_PRECOMPUTED_CLASS_TOGGLES) {
10821
+ if (staticParts.length) return callRuntime("_attr_class", buildClassString(staticParts, dynamicValues));
10822
+ return;
10823
+ }
10824
+ const combos = [];
10825
+ for (let mask = 0; mask < 1 << dynamicValues.length; mask++) {
10826
+ const parts = [...staticParts];
10827
+ for (let i = 0; i < dynamicValues.length; i++) {
10828
+ const { key, alternate } = dynamicValues[i];
10829
+ const part = mask & 1 << i ? key : alternate;
10830
+ if (part) parts.push(part);
10831
+ }
10832
+ combos.push(parts);
10833
+ }
10834
+ if (combos.every((parts) => parts.every(isLiteralPart))) return buildPrecomputedClass(combos.map((parts) => getHTMLRuntime()._attr_class(parts.join(" "))), dynamicValues);
10835
+ const table = getHoistedClassMarkup(combos);
10836
+ return dynamicValues.length ? _marko_compiler.types.memberExpression(table, buildToggleIndex(dynamicValues), true) : table;
10837
+ }
10838
+ function buildPrecomputedClass(combos, toggles) {
10839
+ if (!toggles.length) return _marko_compiler.types.stringLiteral(combos[0]);
10840
+ if (toggles.length === 1) return _marko_compiler.types.conditionalExpression(toggles[0].value, _marko_compiler.types.stringLiteral(combos[1]), _marko_compiler.types.stringLiteral(combos[0]));
10841
+ const end = commonAttrPrefixEnd(combos);
10842
+ const table = generateUidIdentifier("class");
10843
+ (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.markoScriptlet([_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(table, _marko_compiler.types.arrayExpression(combos.map((combo) => _marko_compiler.types.stringLiteral(combo.slice(end)))))])], true));
10844
+ const lookup = _marko_compiler.types.memberExpression(_marko_compiler.types.cloneNode(table), buildToggleIndex(toggles), true);
10845
+ return normalizeStringExpression([combos[0].slice(0, end), lookup]);
10846
+ }
10847
+ const [getHoistedClassMarkups] = createProgramState(() => /* @__PURE__ */ new Map());
10848
+ function getHoistedClassMarkup(combos) {
10849
+ const key = JSON.stringify(combos);
10850
+ const hoisted = getHoistedClassMarkups();
10851
+ let id = hoisted.get(key);
10852
+ if (!id) {
10853
+ const markups = combos.map((parts) => parts.length ? callRuntime("_attr_class", buildClassString(parts, [])) : _marko_compiler.types.stringLiteral(""));
10854
+ hoisted.set(key, id = generateUidIdentifier("class"));
10855
+ (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.markoScriptlet([_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(id, markups.length === 1 ? markups[0] : _marko_compiler.types.arrayExpression(markups))])], true));
10856
+ }
10857
+ return _marko_compiler.types.cloneNode(id);
10858
+ }
10859
+ function buildClassTogglesAssert({ staticParts, dynamicValues }) {
10860
+ if (isOptimize() || !dynamicValues || [...staticParts, ...dynamicValues.flatMap(({ key, alternate }) => [key, alternate])].every((part) => part === void 0 || isLiteralPart(part))) return;
10861
+ return callRuntime("_assert_class_toggles", buildClassString(staticParts, []), _marko_compiler.types.arrayExpression(dynamicValues.map(({ key, alternate }) => buildClassString(alternate ? [key, alternate] : [key], []))));
10862
+ }
10863
+ function buildToggleIndex(toggles) {
10864
+ let index = _marko_compiler.types.conditionalExpression(toggles[0].value, _marko_compiler.types.numericLiteral(1), _marko_compiler.types.numericLiteral(0));
10865
+ for (let i = 1; i < toggles.length; i++) index = _marko_compiler.types.binaryExpression("+", index, _marko_compiler.types.conditionalExpression(toggles[i].value, _marko_compiler.types.numericLiteral(1 << i), _marko_compiler.types.numericLiteral(0)));
10866
+ return index;
10867
+ }
10868
+ function buildClassString(parts, toggles) {
10869
+ const strs = [];
10870
+ for (let i = 0; i < parts.length; i++) {
10871
+ if (i) strs.push(" ");
10872
+ strs.push(toClassPartExpression(parts[i]));
10873
+ }
10874
+ for (const { key, value, alternate } of toggles) strs.push(_marko_compiler.types.conditionalExpression(value, toSpacedClassPart(key), toSpacedClassPart(alternate)));
10875
+ return normalizeStringExpression(strs) || _marko_compiler.types.stringLiteral("");
10876
+ }
10877
+ function toClassPartExpression(part) {
10878
+ return isLiteralPart(part) ? _marko_compiler.types.stringLiteral(part) : toModuleReadExpression(part);
10879
+ }
10880
+ function toSpacedClassPart(part) {
10881
+ return part === void 0 ? _marko_compiler.types.stringLiteral("") : isLiteralPart(part) ? _marko_compiler.types.stringLiteral(" " + part) : _marko_compiler.types.binaryExpression("+", _marko_compiler.types.stringLiteral(" "), toModuleReadExpression(part));
10882
+ }
10883
+ const delimitedAttrStringify = {
10884
+ class: [" ", stringifyClassObject],
10885
+ style: [";", stringifyStyleObject]
10886
+ };
10887
+ function assertUniqueClassToggles(tag, attr, { staticParts, dynamicValues = [] }) {
10888
+ const written = new Set(staticParts.flatMap(getClassNames));
10889
+ for (const { key, alternate } of dynamicValues) {
10890
+ const names = /* @__PURE__ */ new Set([...getClassNames(key), ...getClassNames(alternate)]);
10891
+ for (const name of names) if (written.has(name)) throw tag.hub.buildError(attr, `The toggled class \`${name}\` is also written by another part of the \`class\` value; a toggled [class name](https://markojs.com/docs/reference/native-tag#class) may appear only once.`, Error);
10892
+ for (const name of names) written.add(name);
10893
+ }
10894
+ }
10895
+ function getClassNames(part) {
10896
+ return part === void 0 ? [] : isLiteralPart(part) ? part.split(/\s+/).filter(Boolean) : [part.join(".")];
10897
+ }
10898
+ function isStaticDelimitedAttr(tag, attr) {
10899
+ const { name, value } = attr;
10900
+ if (name !== "class" && name !== "style") return false;
10901
+ const meta = trackDelimitedAttrValue(tag, name, value);
10902
+ if (name === "class") assertUniqueClassToggles(tag, attr, meta);
10903
+ return !meta.dynamic && !meta.dynamicValues;
10904
+ }
10905
+ function getDelimitedAttrItems(name, { dynamic, dynamicValues }) {
10906
+ if (dynamic) return;
10907
+ const items = [];
10908
+ if (!dynamicValues) return items;
10909
+ const keys = /* @__PURE__ */ new Set();
10910
+ for (const { key, value, alternate } of dynamicValues) {
10911
+ if (alternate !== void 0 || name === "style" && (!isLiteralPart(key) || /\s/.test(key) || keys.size === keys.add(key).size)) return;
10912
+ items.push({
10913
+ key,
10914
+ value
10915
+ });
10916
+ }
10917
+ return items;
10918
+ }
10919
+ function isLiteralPart(part) {
10920
+ return typeof part === "string";
10921
+ }
10922
+ function trackDelimitedAttrValue(tag, name, value) {
10689
10923
  const meta = {
10690
- staticItems: void 0,
10691
- dynamicItems: void 0,
10924
+ dynamic: false,
10925
+ staticParts: [],
10692
10926
  dynamicValues: void 0
10693
10927
  };
10694
- trackDelimitedAttrValue(value, meta);
10695
- if (meta.dynamicItems || !meta.staticItems || !meta.dynamicValues) return;
10696
- const base = toDelimitedString(meta.staticItems, " ", stringifyClassObject);
10697
- if (!base) return;
10698
- const { _attr_class } = getHTMLRuntime();
10699
- const keys = Object.keys(meta.dynamicValues);
10700
- if (keys.length === 1) {
10701
- const [key] = keys;
10702
- return _marko_compiler.types.conditionalExpression(meta.dynamicValues[key], _marko_compiler.types.stringLiteral(_attr_class(base + " " + key)), _marko_compiler.types.stringLiteral(_attr_class(base)));
10703
- }
10704
- if (keys.length <= MAX_PRECOMPUTED_CLASS_TOGGLES) {
10705
- const combos = [];
10706
- for (let mask = 0; mask < 1 << keys.length; mask++) {
10707
- let classes = base;
10708
- for (let i = 0; i < keys.length; i++) if (mask & 1 << i) classes += " " + keys[i];
10709
- combos.push(_attr_class(classes));
10710
- }
10711
- const end = commonAttrPrefixEnd(combos);
10712
- const table = generateUidIdentifier("class");
10713
- (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.markoScriptlet([_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(table, _marko_compiler.types.arrayExpression(combos.map((combo) => _marko_compiler.types.stringLiteral(combo.slice(end)))))])], true));
10714
- let index = _marko_compiler.types.conditionalExpression(meta.dynamicValues[keys[0]], _marko_compiler.types.numericLiteral(1), _marko_compiler.types.numericLiteral(0));
10715
- for (let i = 1; i < keys.length; i++) index = _marko_compiler.types.binaryExpression("+", index, _marko_compiler.types.conditionalExpression(meta.dynamicValues[keys[i]], _marko_compiler.types.numericLiteral(1 << i), _marko_compiler.types.numericLiteral(0)));
10716
- const lookup = _marko_compiler.types.memberExpression(_marko_compiler.types.cloneNode(table), index, true);
10717
- return normalizeStringExpression([combos[0].slice(0, end), lookup]);
10718
- }
10719
- let classes = _marko_compiler.types.stringLiteral(base);
10720
- for (const key of keys) classes = _marko_compiler.types.binaryExpression("+", classes, _marko_compiler.types.conditionalExpression(meta.dynamicValues[key], _marko_compiler.types.stringLiteral(" " + key), _marko_compiler.types.stringLiteral("")));
10721
- return callRuntime("_attr_class", classes);
10722
- }
10723
- function trackDelimitedAttrValue(expr, meta) {
10724
- switch (expr.type) {
10725
- case "ObjectExpression":
10726
- trackDelimitedAttrObjectProperties(expr, meta);
10727
- break;
10728
- case "ArrayExpression":
10729
- trackDelimitedAttrArrayItems(expr, meta);
10730
- break;
10731
- default: (meta.dynamicItems ||= []).push(expr);
10732
- }
10928
+ trackDelimitedAttrItem(tag, name, value, meta);
10929
+ return meta;
10733
10930
  }
10734
- function trackDelimitedAttrArrayItems(arr, meta) {
10735
- for (const item of arr.elements) if (item) switch (item.type) {
10931
+ function trackDelimitedAttrItem(tag, name, item, meta) {
10932
+ switch (item.type) {
10736
10933
  case "ArrayExpression":
10737
- trackDelimitedAttrArrayItems(item, meta);
10738
- break;
10739
- case "ObjectExpression":
10740
- trackDelimitedAttrObjectProperties(item, meta);
10741
- break;
10934
+ for (const child of item.elements) if (child) trackDelimitedAttrItem(tag, name, child, meta);
10935
+ return;
10742
10936
  case "SpreadElement":
10743
- if (item.argument.type === "ArrayExpression") trackDelimitedAttrArrayItems(item.argument, meta);
10744
- else (meta.dynamicItems ||= []).push(item);
10745
- break;
10746
- default: {
10747
- const evalItem = evaluate(item);
10748
- if (evalItem.confident) (meta.staticItems ||= []).push(evalItem.computed);
10749
- else (meta.dynamicItems ||= []).push(item);
10750
- break;
10751
- }
10937
+ if (item.argument.type === "ArrayExpression") trackDelimitedAttrItem(tag, name, item.argument, meta);
10938
+ else meta.dynamic = true;
10939
+ return;
10940
+ case "ObjectExpression":
10941
+ trackDelimitedAttrObjectProperties(tag, name, item, meta);
10942
+ return;
10752
10943
  }
10753
- }
10754
- function trackDelimitedAttrObjectProperties(obj, meta) {
10755
- let staticProps;
10756
- let dynamicProps;
10944
+ const part = getDelimitedAttrPart(tag, name, item);
10945
+ if (part !== void 0) {
10946
+ if (part) meta.staticParts.push(part);
10947
+ } else if (name === "class" && item.type === "LogicalExpression") {
10948
+ const key = item.operator === "&&" && getDelimitedAttrPart(tag, name, item.right);
10949
+ if (key) addDynamicValue(meta, key, item.left, void 0);
10950
+ else meta.dynamic = true;
10951
+ } else if (name === "class" && item.type === "ConditionalExpression") {
10952
+ const key = getDelimitedAttrPart(tag, name, item.consequent);
10953
+ const alternate = getDelimitedAttrPart(tag, name, item.alternate);
10954
+ if (key && alternate !== void 0) addDynamicValue(meta, key, item.test, alternate || void 0);
10955
+ else meta.dynamic = true;
10956
+ } else meta.dynamic = true;
10957
+ }
10958
+ function trackDelimitedAttrObjectProperties(tag, name, obj, meta) {
10757
10959
  for (const prop of obj.properties) {
10758
- if (prop.type !== "ObjectProperty" || prop.computed) {
10759
- (dynamicProps ||= []).push(prop);
10760
- continue;
10761
- }
10762
- let key;
10763
- if (prop.key.type === "Identifier") key = prop.key.name;
10764
- else {
10765
- const keyEval = evaluate(prop.key);
10766
- if (keyEval.confident && typeof keyEval.computed === "string" && !/^$|\s/.test(keyEval.computed)) key = keyEval.computed + "";
10767
- else {
10768
- (dynamicProps ||= []).push(prop);
10769
- continue;
10770
- }
10960
+ const key = prop.type === "ObjectProperty" ? getDelimitedAttrKey(tag, name, prop) : void 0;
10961
+ if (!key || prop.type !== "ObjectProperty") {
10962
+ meta.dynamic = true;
10963
+ return;
10771
10964
  }
10772
10965
  const value = prop.value;
10773
- const propEval = evaluate(value);
10774
- if (propEval.confident) (staticProps ||= {})[key] = propEval.computed;
10775
- else (meta.dynamicValues ||= {})[key] = value;
10966
+ const { confident, computed } = evaluate(value);
10967
+ if (!confident) addDynamicValue(meta, key, value, void 0);
10968
+ else if (!isLiteralPart(key)) {
10969
+ if (computed) meta.staticParts.push(key);
10970
+ } else {
10971
+ const part = delimitedAttrStringify[name][1](key, computed);
10972
+ if (part) meta.staticParts.push(part);
10973
+ }
10776
10974
  }
10777
- if (staticProps) (meta.staticItems ||= []).push(staticProps);
10778
- if (dynamicProps) (meta.dynamicItems ||= []).push(_marko_compiler.types.objectExpression(dynamicProps));
10975
+ }
10976
+ function getDelimitedAttrKey(tag, name, prop) {
10977
+ if (!prop.computed && prop.key.type === "Identifier") return prop.key.name;
10978
+ const key = prop.key;
10979
+ const { confident, computed } = evaluate(key);
10980
+ if (confident) return typeof computed === "string" || typeof computed === "number" ? computed + "" : void 0;
10981
+ if (name === "class") return getStyleImportRead(tag, key);
10982
+ }
10983
+ function getDelimitedAttrPart(tag, name, value) {
10984
+ const { confident, computed } = evaluate(value);
10985
+ if (confident) {
10986
+ const [delimiter, stringify] = delimitedAttrStringify[name];
10987
+ return toDelimitedString(computed, delimiter, stringify);
10988
+ }
10989
+ if (name === "class") return getStyleImportRead(tag, value);
10990
+ }
10991
+ function addDynamicValue(meta, key, value, alternate) {
10992
+ (meta.dynamicValues ||= []).push({
10993
+ key,
10994
+ value,
10995
+ alternate
10996
+ });
10779
10997
  }
10780
10998
  function buildUndefined() {
10781
10999
  return _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0));
@@ -10824,9 +11042,10 @@ var dynamic_tag_default = {
10824
11042
  if (tag.node.extra?.tagNameUnresolved) throw tagNotFoundError(tag);
10825
11043
  (0, _marko_compiler_babel_utils.assertAttributesOrArgs)(tag);
10826
11044
  const { node } = tag;
11045
+ if (node.var && node.extra.featureType === "class") throw tag.get("var").buildCodeFrameError(`The Marko 5 (class API) tag \`${getStaticTagName(node)}\` cannot [\`<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 migrate the tag to the tags API.`);
10827
11046
  const definedBodySection = node.extra?.defineBodySection;
10828
11047
  if (definedBodySection) {
10829
- knownTagAnalyze(tag, definedBodySection, definedBodySection.params && getBindingPropTree(definedBodySection.params, !isSameOrChildSection(definedBodySection, getOrCreateSection(tag))));
11048
+ knownTagAnalyze(tag, definedBodySection);
10830
11049
  child(tag, getStaticTagName(tag.node), {
10831
11050
  kind: SectionRef,
10832
11051
  section: definedBodySection
@@ -10960,10 +11179,10 @@ var dynamic_tag_default = {
10960
11179
  const bodySection = getSectionForBody(tag.get("body"));
10961
11180
  const signal = getSignal(section, nodeBinding, "dynamicTag");
10962
11181
  let tagVarSignal;
10963
- if (tag.node.var) {
11182
+ if (tag.node.var && isTagVarResumed(tag)) {
10964
11183
  const varBinding = tag.node.var.extra.binding;
10965
11184
  tagVarSignal = initValue(varBinding);
10966
- tagVarSignal.register = isTagVarResumed(tag);
11185
+ tagVarSignal.register = true;
10967
11186
  tagVarSignal.referenced = true;
10968
11187
  tagVarSignal.buildAssignment = (valueSection, value) => {
10969
11188
  const changeArgs = [_marko_compiler.types.memberExpression(getScopeExpression(tagVarSignal.section, valueSection), _marko_compiler.types.stringLiteral(getAccessorPrefix().BranchScopes + getScopeAccessor(nodeBinding)), true), value];
@@ -10981,9 +11200,9 @@ var dynamic_tag_default = {
10981
11200
  const argsOrInput = hasTagArgs ? _marko_compiler.types.arrayExpression(args) : args[0];
10982
11201
  if (!_marko_compiler.types.isObjectExpression(argsOrInput) || argsOrInput.properties.length) signal.extraArgs = [_marko_compiler.types.arrowFunctionExpression([], statements.length ? _marko_compiler.types.blockStatement(statements.concat(_marko_compiler.types.returnStatement(argsOrInput))) : argsOrInput)];
10983
11202
  }
11203
+ enableDynamicTagVar(tag);
10984
11204
  if (!isClassAPI) {
10985
11205
  enableDynamicTagResume(tag);
10986
- enableDynamicTagVar(tag);
10987
11206
  enableDynamicTagControllables(tag);
10988
11207
  }
10989
11208
  addValue(section, getReferencedBindings(tagExtra), signal, tagExpression);
@@ -11002,9 +11221,9 @@ function enableDynamicTagControllables(tag) {
11002
11221
  }
11003
11222
  }
11004
11223
  function enableDynamicTagVar(tag) {
11005
- if (!tag.node.var || !isTagVarResumed(tag) || analyzeTagNameType(tag, true) === 1) return;
11224
+ if (!tag.node.var || !isTagVarResumed(tag)) return;
11006
11225
  importRuntimeFeature("dynamic-tag-var");
11007
- if (!tag.node.var.extra.binding.pruned) {
11226
+ if (analyzeTagNameType(tag, true) !== 1 && !tag.node.var.extra.binding.pruned) {
11008
11227
  const accessor = getScopeAccessorLiteral(tag.node.extra.nodeBinding, true);
11009
11228
  if (addRuntimeOnce(`_dynamic_tag_var_resume ${accessor.value}`)) (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.expressionStatement(callRuntime("_dynamic_tag_var_resume", accessor)));
11010
11229
  }