marko 6.4.1 → 6.4.2

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 (73) hide show
  1. package/cheatsheet.md +1 -1
  2. package/dist/common/errors.d.ts +1 -0
  3. package/dist/common/opt.d.ts +1 -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 +1 -1
  19. package/dist/debug/dom/dynamic-tag-var.feat.mjs +1 -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-ClV4kVOO.js → dom-BLbR0hEx.js} +30 -0
  25. package/dist/debug/{dom-LFrKxOk5.mjs → dom-Cii0IA92.mjs} +19 -1
  26. package/dist/debug/dom.js +7 -4
  27. package/dist/debug/dom.mjs +6 -5
  28. package/dist/debug/html.js +280 -76
  29. package/dist/debug/html.mjs +280 -77
  30. package/dist/dom/catch.feat.js +3 -3
  31. package/dist/dom/catch.feat.mjs +1 -1
  32. package/dist/dom/controllable-input.feat.js +1 -1
  33. package/dist/dom/controllable-input.feat.mjs +1 -1
  34. package/dist/dom/controllable-open.feat.js +1 -1
  35. package/dist/dom/controllable-open.feat.mjs +1 -1
  36. package/dist/dom/controllable-select.feat.js +1 -1
  37. package/dist/dom/controllable-select.feat.mjs +1 -1
  38. package/dist/dom/controllable-textarea.feat.js +1 -1
  39. package/dist/dom/controllable-textarea.feat.mjs +1 -1
  40. package/dist/dom/controllable.feat.js +1 -1
  41. package/dist/dom/controllable.feat.mjs +1 -1
  42. package/dist/dom/dom.d.ts +1 -0
  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 +1 -1
  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/placeholder.feat.js +3 -3
  50. package/dist/dom/placeholder.feat.mjs +1 -1
  51. package/dist/{dom-CNglVi8P.js → dom-B8UEYzOz.js} +99 -80
  52. package/dist/{dom-DfP3MCo0.mjs → dom-BPjLe6YU.mjs} +10 -1
  53. package/dist/dom.d.ts +2 -2
  54. package/dist/dom.js +34 -33
  55. package/dist/dom.mjs +6 -5
  56. package/dist/html/assets.d.ts +12 -6
  57. package/dist/html/attrs.d.ts +1 -0
  58. package/dist/html/compat.d.ts +10 -2
  59. package/dist/html/serializer.d.ts +1 -0
  60. package/dist/html/writer.d.ts +8 -0
  61. package/dist/html.d.ts +1 -1
  62. package/dist/html.js +194 -59
  63. package/dist/html.mjs +194 -59
  64. package/dist/translator/index.js +404 -190
  65. package/dist/translator/util/bindings.d.ts +9 -1
  66. package/dist/translator/util/constants/structure-kind.d.ts +1 -0
  67. package/dist/translator/util/known-tag.d.ts +2 -1
  68. package/dist/translator/util/module-read.d.ts +21 -0
  69. package/dist/translator/util/references.d.ts +1 -0
  70. package/dist/translator/util/runtime.d.ts +2 -0
  71. package/dist/translator/util/sections.d.ts +5 -1
  72. package/dist/translator/util/structure.d.ts +1 -0
  73. package/package.json +3 -3
@@ -797,6 +797,11 @@ function isInvokedFunction(expr) {
797
797
  return false;
798
798
  }
799
799
  //#endregion
800
+ //#region src/translator/util/is-static.ts
801
+ function isStatic(path) {
802
+ return path.isImportDeclaration() || path.isExportDeclaration() || path.isMarkoScriptlet({ static: true });
803
+ }
804
+ //#endregion
800
805
  //#region src/translator/util/binding-has-prop.ts
801
806
  function getSectionRendererIdentifier(section) {
802
807
  return isSectionRendererElided(section) ? void 0 : _marko_compiler.types.identifier(section.name);
@@ -829,6 +834,7 @@ function getPropertyPathAlias(binding, properties) {
829
834
  const Node = "node";
830
835
  const Text = "text";
831
836
  const Child = "child";
837
+ const ModuleRead = "moduleRead";
832
838
  const SectionRef = "sectionRef";
833
839
  const ExportRef = "exportRef";
834
840
  //#endregion
@@ -968,7 +974,7 @@ var function_default = { analyze(fn) {
968
974
  fnExtra.exprRoot = exprRoot.node.extra ??= {};
969
975
  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
976
  reserveExportRegisterId(fnExtra, fn, markoRoot);
971
- if (isStaticRoot(markoRoot)) {
977
+ if (isStatic(markoRoot)) {
972
978
  const refs = getStaticDeclRefs(fn);
973
979
  if (refs.size) getReferencesByFn().set(fnExtra, refs);
974
980
  } else getReferencesByFn().set(fnExtra, /* @__PURE__ */ new Set([fnExtra.exprRoot]));
@@ -1047,7 +1053,7 @@ function registerImportedFn({ node, ...importedFn }) {
1047
1053
  (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
1048
1054
  }
1049
1055
  function reserveExportRegisterId(fnExtra, fn, markoRoot) {
1050
- if (!isStaticRoot(markoRoot)) return;
1056
+ if (!isStatic(markoRoot)) return;
1051
1057
  const exportNames = getExportNames(fn, markoRoot);
1052
1058
  const exportName = exportNames?.find((name) => _marko_compiler.types.isValidIdentifier(name));
1053
1059
  if (!exportName) return;
@@ -1105,7 +1111,7 @@ function addBindingRefs(binding, refs, seen) {
1105
1111
  const exprRoot = getExprRoot(ref);
1106
1112
  const markoRoot = getMarkoRoot(exprRoot);
1107
1113
  if (!markoRoot || canIgnoreRegister(markoRoot, exprRoot)) continue;
1108
- if (isStaticRoot(markoRoot)) getStaticDeclRefs(ref, refs, seen);
1114
+ if (isStatic(markoRoot)) getStaticDeclRefs(ref, refs, seen);
1109
1115
  else refs.add(exprRoot.node.extra ??= {});
1110
1116
  }
1111
1117
  }
@@ -1118,14 +1124,6 @@ function registerFunction(fnExtra) {
1118
1124
  function isMarkoAttribute(path) {
1119
1125
  return path ? path.isMarkoAttribute() : false;
1120
1126
  }
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
1127
  //#endregion
1130
1128
  //#region src/translator/util/cyclic-memo.ts
1131
1129
  function createCyclicMemo(compute, cycleAnswer) {
@@ -1749,7 +1747,8 @@ function getHTMLRuntime() {
1749
1747
  _attr_class,
1750
1748
  _attr_style,
1751
1749
  _escape_script,
1752
- _escape_style
1750
+ _escape_style,
1751
+ escapeDoubleQuotedAttrValue
1753
1752
  };
1754
1753
  }
1755
1754
  function getRuntimePath(output) {
@@ -2224,7 +2223,7 @@ function getOrCreateHtmlLoadWrapped(readyId, originalIdentifier, filename, trigg
2224
2223
  markoOpts.linkAssets?.onAsset("load", filename, readyId);
2225
2224
  const wrappedName = generateUid(`${originalIdentifier.name ?? "tag"}_withLoadAssets`);
2226
2225
  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));
2226
+ (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
2227
  return wrappedName;
2229
2228
  }
2230
2229
  function trackImportedRegisteredFns(importDecl) {
@@ -2640,8 +2639,16 @@ function normalizeStringExpression(parts, useIife) {
2640
2639
  if (exprs.length === 1 && !curStr && !strs[0]) return exprs[0];
2641
2640
  strs.push(curStr);
2642
2641
  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);
2642
+ const args = [];
2643
+ const params = [];
2644
+ const body = _marko_compiler.types.templateLiteral(strs.map((raw) => _marko_compiler.types.templateElement({ raw: escapeTemplateRaw(raw) })), exprs.map((expr) => {
2645
+ if (expr.type !== "Identifier") return expr;
2646
+ const param = _marko_compiler.types.identifier(`_w${params.length}`);
2647
+ params.push(param);
2648
+ args.push(expr);
2649
+ return param;
2650
+ }));
2651
+ const iife = _marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression(params, body), args);
2645
2652
  _marko_compiler.types.addComment(iife, "leading", "@__PURE__");
2646
2653
  return iife;
2647
2654
  }
@@ -2960,8 +2967,8 @@ function getDeclaredBindingExpression(binding, inPlace = false) {
2960
2967
  if (canonicalBinding.localOf) return getDeclaredBindingExpression(canonicalBinding.localOf, inPlace);
2961
2968
  const { aliasOf: aliased, property, declaredAlias } = canonicalBinding;
2962
2969
  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);
2970
+ if (canonicalBinding.declared || isRest(canonicalBinding)) return _marko_compiler.types.identifier(canonicalBinding.name);
2971
+ if (declaredAlias && !isRest(declaredAlias) && !getNearestDeclared(canonicalBinding)) return _marko_compiler.types.identifier(declaredAlias.name);
2965
2972
  if (!aliased) return _marko_compiler.types.identifier(canonicalBinding.name);
2966
2973
  if (property !== void 0) {
2967
2974
  const alias = !getNearestDeclared(aliased) && aliased.declaredAlias;
@@ -3091,7 +3098,7 @@ function translateVar(tag, initialValue, kind = "const", statements) {
3091
3098
  if (binding.declared) {
3092
3099
  if (binding.section === section) allPruned = false;
3093
3100
  else translateAliasInSection(tag, id, binding, kind);
3094
- } else if (binding.excludeProperties !== void 0) translateRest(tag, id, binding, kind);
3101
+ } else if (isRest(binding)) translateRest(tag, id, binding, kind);
3095
3102
  });
3096
3103
  if (allPruned) return;
3097
3104
  removeUndeclared(tagVar, section);
@@ -3108,7 +3115,7 @@ function translateVar(tag, initialValue, kind = "const", statements) {
3108
3115
  const changeBinding = binding.aliasOf.propertyAliases.get(changeName);
3109
3116
  if (changeBinding && changeName !== changeBinding.name) {
3110
3117
  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)));
3118
+ if (pattern) pattern.unshiftContainer("properties", _marko_compiler.types.objectProperty(toPropertyName(changeName), _marko_compiler.types.identifier(changeBinding.name)));
3112
3119
  }
3113
3120
  }
3114
3121
  });
@@ -3159,11 +3166,11 @@ function translateRest(tag, id, rest, kind) {
3159
3166
  }
3160
3167
  function getRestPattern(rest, id, from, shorthand) {
3161
3168
  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]);
3169
+ if (rest.restOffset !== void 0) return _marko_compiler.types.arrayPattern([...new Array(rest.restOffset - (from.restOffset || 0)).fill(null), restElement]);
3163
3170
  return _marko_compiler.types.objectPattern([...toArray(rest.excludeProperties, shorthand ? (name) => name === id.name ? toExcludedProperty(name) : toShorthandExcludedProperty(name) : toExcludedProperty), restElement]);
3164
3171
  }
3165
3172
  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;
3173
+ return from.nullable ? _marko_compiler.types.logicalExpression("||", value, rest.restOffset !== void 0 ? _marko_compiler.types.arrayExpression([]) : _marko_compiler.types.objectExpression([])) : value;
3167
3174
  }
3168
3175
  function getSectionTarget(tag, section) {
3169
3176
  let target = tag;
@@ -3376,7 +3383,7 @@ function getSignalFn(signal) {
3376
3383
  const aliasSignal = getSignal(alias.section, alias);
3377
3384
  if (signalHasStatements(aliasSignal)) {
3378
3385
  signal.forwards = push(signal.forwards, aliasSignal);
3379
- if (alias.excludeProperties !== void 0) {
3386
+ if (isRest(alias)) {
3380
3387
  const aliasId = _marko_compiler.types.identifier(alias.name);
3381
3388
  signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(aliasSignal.identifier, [
3382
3389
  scopeIdentifier,
@@ -3912,6 +3919,52 @@ function isOnlyChild(tag) {
3912
3919
  return true;
3913
3920
  }
3914
3921
  //#endregion
3922
+ //#region src/translator/util/module-read.ts
3923
+ const styleImportReg = /\.(?:css(?:\.[cm]?[jt]s)?|less|s[ac]ss|styl(?:us)?|pcss|postcss)(?:\?|$)/i;
3924
+ const kModuleRead = Symbol("module read");
3925
+ /** The module read an expression is, resolved on first use: translate replaces
3926
+ * a `<style/name>` tag. */
3927
+ function getModuleRead(path, expr) {
3928
+ return ((expr.extra ??= {})[kModuleRead] ??= resolveModuleRead(path, expr)) || void 0;
3929
+ }
3930
+ /** A module read of a stylesheet module, whose reads are class name strings. */
3931
+ function getStyleImportRead(path, expr) {
3932
+ const moduleRead = getModuleRead(path, expr);
3933
+ if (moduleRead && (moduleRead.request === void 0 || styleImportReg.test(moduleRead.request))) return moduleRead.read;
3934
+ }
3935
+ function toModuleReadExpression([name, ...members]) {
3936
+ let expr = _marko_compiler.types.identifier(name);
3937
+ for (const member of members) expr = _marko_compiler.types.memberExpression(expr, _marko_compiler.types.identifier(member));
3938
+ return expr;
3939
+ }
3940
+ function resolveModuleRead(path, expr) {
3941
+ switch (expr.type) {
3942
+ case "Identifier": {
3943
+ const decl = path.scope.getBinding(expr.name)?.path;
3944
+ const importDecl = decl?.parentPath;
3945
+ if (importDecl?.isImportDeclaration()) {
3946
+ const scriptlet = importDecl.parentPath;
3947
+ return scriptlet.isMarkoScriptlet() && scriptlet.node.target ? null : {
3948
+ read: [expr.name],
3949
+ request: importDecl.node.source.value
3950
+ };
3951
+ }
3952
+ return decl && isCoreTagName(decl, "style") && decl.node.var.type === "Identifier" ? {
3953
+ read: [expr.name],
3954
+ request: void 0
3955
+ } : null;
3956
+ }
3957
+ case "MemberExpression": {
3958
+ const object = !expr.computed && getModuleRead(path, expr.object);
3959
+ return object ? {
3960
+ read: [...object.read, expr.property.name],
3961
+ request: object.request
3962
+ } : null;
3963
+ }
3964
+ }
3965
+ return null;
3966
+ }
3967
+ //#endregion
3915
3968
  //#region src/translator/util/structure.ts
3916
3969
  const walkCodeToName = {
3917
3970
  [32]: "get",
@@ -3958,6 +4011,12 @@ function writeTo(path) {
3958
4011
  }
3959
4012
  };
3960
4013
  }
4014
+ function writeModuleReadTo(path, read) {
4015
+ getSection(path).structure?.push({
4016
+ kind: ModuleRead,
4017
+ read
4018
+ });
4019
+ }
3961
4020
  function writeTextTo(path, value) {
3962
4021
  if (value) getSection(path).structure?.push({
3963
4022
  kind: Text,
@@ -4018,6 +4077,10 @@ function resolveStructure(section) {
4018
4077
  appendLiteral(resolved.writes, op.value);
4019
4078
  textEdge = "own";
4020
4079
  break;
4080
+ case ModuleRead:
4081
+ resolved.writes.push(toModuleReadExpression(op.read), "");
4082
+ textEdge = void 0;
4083
+ break;
4021
4084
  case Node: {
4022
4085
  if (!op.binding) continue;
4023
4086
  const withVar = hasScopeOffset(op.binding);
@@ -4266,11 +4329,6 @@ function assertSetupWorkFound(program, section, written) {
4266
4329
  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
4330
  }
4268
4331
  //#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
4332
  //#region src/translator/visitors/program/html.ts
4275
4333
  function getTemplateContentName() {
4276
4334
  return getSharedUid("content");
@@ -4758,7 +4816,7 @@ var custom_tag_default = {
4758
4816
  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
4817
  if (childExtra.page) programExtra.page ??= true;
4760
4818
  if (tagExtra.tagNameLoad) tagExtra[kLoadTagBinding] = createBinding("#text", 0, getOrCreateSection(tag));
4761
- knownTagAnalyze(tag, childSection, programSection === childSection ? programSection.params && getBindingPropTree(programSection.params) : childExtra.paramsTree);
4819
+ knownTagAnalyze(tag, childSection, childExtra.paramsTree);
4762
4820
  const tagName = getStaticTagName(tag.node);
4763
4821
  if (tagExtra.tagNameLoad) {
4764
4822
  marker(tag, tagExtra[kLoadTagBinding]);
@@ -5236,6 +5294,7 @@ var program_default = {
5236
5294
  },
5237
5295
  exit(program) {
5238
5296
  if (hasAnalyzeErrors()) return;
5297
+ analyzeRecursiveTags();
5239
5298
  finalizeReferences();
5240
5299
  const programExtra = program.node.extra;
5241
5300
  const paramsBinding = programExtra.binding;
@@ -5786,33 +5845,51 @@ const [getKnownTags] = createSectionState("known tags", () => []);
5786
5845
  const kContentSection = Symbol("known tag content section");
5787
5846
  const kPropTree = Symbol("known tag prop tree");
5788
5847
  const kKnownExprs = Symbol("known tag exprs");
5789
- function knownTagAnalyze(tag, contentSection, propTree) {
5848
+ const [getRecursiveTags] = createProgramState(() => []);
5849
+ function knownTagAnalyze(tag, contentSection, childParamsTree) {
5790
5850
  analyzeAttributeTags(tag);
5791
5851
  const section = getOrCreateSection(tag);
5792
5852
  const tagBody = tag.get("body");
5793
5853
  const tagExtra = tag.node.extra ??= {};
5794
- const childScopeBinding = tagExtra.nodeBinding = createBinding("#childScope", 0, section);
5795
- const attrExprs = /* @__PURE__ */ new Set([tagExtra]);
5854
+ tagExtra.nodeBinding = createBinding("#childScope", 0, section);
5796
5855
  startSection(tagBody);
5797
5856
  trackParamsReferences(tagBody, 2);
5798
5857
  getKnownTags(section).push(tagExtra);
5799
5858
  tagExtra[kContentSection] = contentSection;
5800
- tagExtra[kPropTree] = propTree;
5801
- if (contentSection.program === section.program) contentSection.callSections = sectionUtil.add(contentSection.callSections, section);
5802
5859
  const varBinding = trackVarReferences(tag, 4);
5803
- const exprs = tagExtra[kKnownExprs] = analyzeParams(tagExtra, section, tag, propTree, attrExprs);
5804
- setTagDerivedFrom(tag, propTree?.props?.[0]?.binding, exprs);
5860
+ const recursive = isSameOrChildSection(contentSection, section);
5861
+ let exprs;
5862
+ if (contentSection.program === section.program) {
5863
+ contentSection.callSections = sectionUtil.add(contentSection.callSections, section);
5864
+ if (recursive) getRecursiveTags().push(tag);
5865
+ else exprs = analyzeKnownTagParams(tag, getParamsTree(contentSection));
5866
+ } else exprs = analyzeKnownTagParams(tag, childParamsTree);
5805
5867
  if (varBinding) {
5806
5868
  addSetupExpr(section);
5807
5869
  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)));
5870
+ const varExpr = recursive || (tagExtra.defineBodySection ? contentSection.returnValueExpr : mapParamReasonToExpr(exprs, getReturnParams(contentSection)));
5871
+ const childScopeBinding = tagExtra.nodeBinding;
5809
5872
  varBinding.returnedBy = childScopeBinding;
5810
5873
  reserveId(childScopeBinding, 1);
5811
5874
  setDerivedFrom(varBinding, varExpr);
5812
5875
  if (mutatesTagVar || varExpr === true) addReason(getSlot(childScopeBinding), ALWAYS);
5813
5876
  if (varExpr !== true) addReasonExprs(getSlot(childScopeBinding), varExpr);
5814
5877
  }
5815
- addReasonExprs(getSlot(childScopeBinding), fromIter(attrExprs));
5878
+ }
5879
+ function analyzeRecursiveTags() {
5880
+ for (const tag of getRecursiveTags()) analyzeKnownTagParams(tag, getParamsTree(tag.node.extra[kContentSection]));
5881
+ }
5882
+ function getParamsTree(contentSection) {
5883
+ return contentSection.params && getBindingPropTree(contentSection.params, true);
5884
+ }
5885
+ function analyzeKnownTagParams(tag, propTree) {
5886
+ const tagExtra = tag.node.extra;
5887
+ const attrExprs = /* @__PURE__ */ new Set([tagExtra]);
5888
+ tagExtra[kPropTree] = propTree;
5889
+ const exprs = tagExtra[kKnownExprs] = analyzeParams(tagExtra, getSection(tag), tag, propTree, attrExprs);
5890
+ setTagDerivedFrom(tag, propTree?.props?.[0]?.binding, exprs);
5891
+ addReasonExprs(getSlot(tagExtra.nodeBinding), fromIter(attrExprs));
5892
+ return exprs;
5816
5893
  }
5817
5894
  function getReturnParams(section) {
5818
5895
  const sources = section.returnValueExpr && getSourcesForExpr(section.returnValueExpr);
@@ -6609,7 +6686,7 @@ function addValueReferences(refs, expr) {
6609
6686
  return isReferencedExtra(getCanonicalExtra(expr)) && !expr.initialValue ? bindingUtil.union(refs, getReferencedBindings(expr)) : refs;
6610
6687
  }
6611
6688
  function getWalkedBinding(op) {
6612
- return typeof op === "object" && op.kind !== "text" ? op.binding : void 0;
6689
+ return typeof op === "object" && (op.kind === "node" || op.kind === "child") ? op.binding : void 0;
6613
6690
  }
6614
6691
  function getLastOwnSourceReturn(intersection, section) {
6615
6692
  let returnedBy;
@@ -6715,18 +6792,20 @@ function pruneBinding(binding) {
6715
6792
  binding.pruned = false;
6716
6793
  for (const read of binding.reads.keys()) if (isDroppableValue(read)) forEach(read.derives, pruneBinding);
6717
6794
  forEach(binding.assignments, pruneWriter);
6795
+ const assignedObject = getAssignedObject(binding);
6718
6796
  for (const [expr, reads] of binding.reads) {
6719
- const owner = getReadOwner(binding.aliasOf, expr);
6797
+ const owner = assignedObject ? getReadOwner(assignedObject, expr) || assignedObject : getReadOwner(binding.aliasOf, expr);
6720
6798
  if (owner) {
6721
6799
  owner.reads.set(expr, concat(owner.reads.get(expr), reads));
6722
6800
  binding.reads.delete(expr);
6723
6801
  }
6724
6802
  }
6725
- let shouldPrune = !binding.reads.size && !(binding.reserveSize && some(binding.assignments, inEmittedExpr));
6803
+ let shouldPrune = true;
6726
6804
  for (const alias of binding.aliases) if (pruneBinding(alias)) binding.aliases.delete(alias);
6727
6805
  else if (alias.type !== 5) shouldPrune = false;
6728
6806
  for (const [key, alias] of binding.propertyAliases) if (pruneBinding(alias)) binding.propertyAliases.delete(key);
6729
6807
  else if (alias.type !== 5) shouldPrune = false;
6808
+ shouldPrune &&= !binding.reads.size && !(binding.reserveSize && some(binding.assignments, inEmittedExpr));
6730
6809
  binding.pruned = shouldPrune;
6731
6810
  if (shouldPrune && !hasEmittedAssignment(binding)) {
6732
6811
  if (binding.derivedFrom) forEach(binding.derivedFrom, dropUnreadValue);
@@ -7462,6 +7541,7 @@ function trackDomVarReferences(tag, binding) {
7462
7541
  binding.originalName = tagVar.name;
7463
7542
  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
7543
  for (const ref of babelBinding.referencePaths) {
7544
+ assertReferencedInRender(ref, tagVar.name);
7465
7545
  const refSection = getOrCreateSection(ref);
7466
7546
  const invoked = isInvokedFunction(ref);
7467
7547
  const hoisted = isReferenceHoisted(babelBinding.path, ref) ? getCommonSection(refSection, binding.section) : false;
@@ -7485,7 +7565,7 @@ function trackVarReferences(tag, type, aliased) {
7485
7565
  let target = aliased && getCanonicalBinding(aliased);
7486
7566
  if (target) {
7487
7567
  const { excludeProperties, restOffset } = target;
7488
- if (excludeProperties !== void 0) target = target.aliasOf;
7568
+ if (isRest(target)) target = target.aliasOf;
7489
7569
  createBindingsAndTrackReferences(tagVar, target.type, tag.scope, section, target, void 0, excludeProperties, restOffset, false);
7490
7570
  return target;
7491
7571
  }
@@ -7503,6 +7583,7 @@ function trackParamsReferences(body, type) {
7503
7583
  if (bodySection) bodySection.params = paramsBinding;
7504
7584
  for (let i = 0; i < params.length; i++) {
7505
7585
  const param = params[i];
7586
+ if (param.type === "RestElement") assertRestNotAssigned(body.scope, param.argument);
7506
7587
  if (i === 0 && param.type === "RestElement" && param.argument.type === "Identifier") {
7507
7588
  const { argument } = param;
7508
7589
  paramsBinding.name = argument.name;
@@ -7544,9 +7625,10 @@ function isReferenceHoisted(bindingPath, reference) {
7544
7625
  function trackReferencesForBinding(babelBinding, binding) {
7545
7626
  const { referencePaths, constantViolations } = babelBinding;
7546
7627
  for (const ref of referencePaths) {
7547
- const refSection = getOrCreateSection(ref);
7548
7628
  const markoRoot = getMarkoRoot(ref);
7549
- if (!binding.declared && binding.excludeProperties === void 0) {
7629
+ assertReferencedInRender(ref, ref.node.name, markoRoot);
7630
+ const refSection = getOrCreateSection(ref);
7631
+ if (!binding.declared && !isRest(binding)) {
7550
7632
  const root = getNearestDeclared(binding);
7551
7633
  binding.declared = !!root && ref.scope.getBinding(root.name) !== babelBinding.scope.getBinding(root.name);
7552
7634
  }
@@ -7573,6 +7655,7 @@ function trackReferencesForBinding(babelBinding, binding) {
7573
7655
  }
7574
7656
  for (const ref of constantViolations) {
7575
7657
  if (ref.type === "MarkoTag") throw ref.get("var").buildCodeFrameError(`Duplicate declaration of \`${binding.name}\`.`);
7658
+ assertReferencedInRender(ref, binding.name);
7576
7659
  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
7660
  if (ref.isUpdateExpression()) trackAssignment(ref.get("argument"), binding);
7578
7661
  else if (ref.isAssignmentExpression()) {
@@ -7588,6 +7671,8 @@ function trackAssignment(assignment, binding) {
7588
7671
  const fnParent = getFnParent(assignment);
7589
7672
  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
7673
  if (binding.type === 3) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag parameter and cannot be assigned to.`);
7674
+ let assigned = binding;
7675
+ while (isDirectAlias(assigned)) assigned = assigned.aliasOf;
7591
7676
  const fnRoot = getFnRoot(fnParent);
7592
7677
  const fnExtra = fnRoot && (fnRoot.node.extra ??= {});
7593
7678
  const section = getOrCreateSection(assignment);
@@ -7595,7 +7680,7 @@ function trackAssignment(assignment, binding) {
7595
7680
  forEachIdentifierPath(assignment, (id) => {
7596
7681
  if (id.node.name === binding.name) {
7597
7682
  const idExtra = id.node.extra ??= {};
7598
- idExtra.assignment = binding;
7683
+ idExtra.assignment = assigned;
7599
7684
  idExtra.section = section;
7600
7685
  idExtra.exprRoot = getExprRoot(fnRoot || assignment).node.extra ??= {};
7601
7686
  idExtra.fnRoot = fnExtra;
@@ -7604,16 +7689,19 @@ function trackAssignment(assignment, binding) {
7604
7689
  fnExtra.section = section;
7605
7690
  fnExtra.exprRoot = idExtra.exprRoot;
7606
7691
  }
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);
7692
+ if (assigned.aliasOf && assigned.property !== void 0) {
7693
+ if (assigned.aliasOf === assigned.section.params) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag parameter and cannot be assigned to.`);
7694
+ const changePropName = assigned.property + "Change";
7695
+ 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
7696
  idExtra.assignmentTo = changeBinding;
7612
7697
  addReadToExpression(id, changeBinding, void 0);
7613
7698
  }
7614
7699
  }
7615
7700
  });
7616
7701
  }
7702
+ function assertReferencedInRender(ref, name, markoRoot = getMarkoRoot(ref)) {
7703
+ 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.`);
7704
+ }
7617
7705
  function setReferencesScope(path) {
7618
7706
  const fnRoot = getFnRoot(path);
7619
7707
  if (fnRoot) (fnRoot.node.extra ??= {}).referencesScope = true;
@@ -7628,8 +7716,7 @@ function createBindingsAndTrackReferences(lVal, type, scope, section, aliased, p
7628
7716
  createBindingsAndTrackReferences(lVal.left, type, scope, section, aliased, property, excludeProperties, restOffset, declared);
7629
7717
  break;
7630
7718
  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;
7719
+ const binding = (lVal.extra ??= {}).binding = createBinding(lVal.name, type, section, aliased, property, excludeProperties, lVal.loc, declared, restOffset);
7633
7720
  trackReferencesForBinding(scope.getBinding(lVal.name), binding);
7634
7721
  break;
7635
7722
  }
@@ -7639,8 +7726,10 @@ function createBindingsAndTrackReferences(lVal, type, scope, section, aliased, p
7639
7726
  const { properties } = lVal;
7640
7727
  const hasRest = properties.length > 0 && properties[properties.length - 1].type === "RestElement";
7641
7728
  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 {
7729
+ for (const prop of lVal.properties) if (prop.type === "RestElement") {
7730
+ assertRestNotAssigned(scope, prop.argument);
7731
+ createBindingsAndTrackReferences(prop.argument, type, scope, section, patternBinding, void 0, excludeProperties, void 0, declaresPattern);
7732
+ } else {
7644
7733
  let key;
7645
7734
  if (!prop.computed && prop.key.type === "Identifier") key = prop.key.name;
7646
7735
  else if (prop.key.type === "StringLiteral") key = prop.key.value;
@@ -7660,6 +7749,7 @@ function createBindingsAndTrackReferences(lVal, type, scope, section, aliased, p
7660
7749
  index++;
7661
7750
  if (element) {
7662
7751
  if (element.type === "RestElement") {
7752
+ assertRestNotAssigned(scope, element.argument);
7663
7753
  excludeProperties = index > 0 ? addNumericPropertiesUntil(excludeProperties, index) : void 0;
7664
7754
  createBindingsAndTrackReferences(element.argument, type, scope, section, patternBinding, void 0, excludeProperties, index, declaresPattern);
7665
7755
  } else if (_marko_compiler.types.isLVal(element)) {
@@ -7678,16 +7768,29 @@ function createBindingsAndTrackReferences(lVal, type, scope, section, aliased, p
7678
7768
  function isAssignment(ref) {
7679
7769
  return ref.type !== "MarkoTag";
7680
7770
  }
7771
+ function assertRestNotAssigned(scope, rest) {
7772
+ if (rest.type === "Identifier") {
7773
+ const assignment = scope.getBinding(rest.name).constantViolations.find(isAssignment);
7774
+ 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.`);
7775
+ }
7776
+ }
7681
7777
  function trackReference(referencePath, binding) {
7682
7778
  let root = referencePath;
7683
7779
  let reference = binding;
7684
7780
  while (true) {
7685
7781
  const { parent } = root;
7686
- if (!_marko_compiler.types.isMemberExpression(parent) && !_marko_compiler.types.isOptionalMemberExpression(parent) || isWrittenMember(root.parentPath)) break;
7782
+ if (!_marko_compiler.types.isMemberExpression(parent) && !_marko_compiler.types.isOptionalMemberExpression(parent)) break;
7687
7783
  let prop = getMemberExpressionPropString(parent);
7784
+ if (isAssignedMember(root.parentPath)) {
7785
+ let object = reference;
7786
+ while (isDirectAlias(object)) object = object.aliasOf;
7787
+ 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>\`.`);
7788
+ addAssignedProperty(object, prop);
7789
+ break;
7790
+ }
7688
7791
  if (prop === void 0) break;
7689
- if (reference.aliasOf && reference.excludeProperties !== void 0) {
7690
- if (reference.restOffset) {
7792
+ if (reference.aliasOf && isRest(reference)) {
7793
+ if (reference.restOffset !== void 0) {
7691
7794
  if (isIndexProperty(prop)) {
7692
7795
  prop = `${+prop + reference.restOffset}`;
7693
7796
  reference = reference.aliasOf;
@@ -7702,7 +7805,7 @@ function trackReference(referencePath, binding) {
7702
7805
  (referencePath.node.extra ??= {}).binding = binding;
7703
7806
  addReadToExpression(root, reference, void 0);
7704
7807
  }
7705
- function isWrittenMember(member) {
7808
+ function isAssignedMember(member) {
7706
7809
  const { node, parent } = member;
7707
7810
  switch (parent.type) {
7708
7811
  case "AssignmentExpression":
@@ -7830,7 +7933,9 @@ function untrackExtra(exprExtra) {
7830
7933
  if (reads) {
7831
7934
  readsByExpr.delete(exprExtra);
7832
7935
  getFunctionReadsByExpression().delete(exprExtra);
7833
- forEach(reads, (read) => read.binding.reads.delete(exprExtra));
7936
+ forEach(reads, (read) => {
7937
+ for (let cur = read.binding; cur; cur = cur.aliasOf) cur.reads.delete(exprExtra);
7938
+ });
7834
7939
  }
7835
7940
  }
7836
7941
  function dropContent(body) {
@@ -7990,7 +8095,7 @@ function getKnownExprsAt(exprs, binding) {
7990
8095
  //#region src/translator/util/bindings.ts
7991
8096
  const [getBindings] = createProgramState(() => /* @__PURE__ */ new Set());
7992
8097
  const [getNextBindingId, setNextBindingId] = createProgramState(() => 0);
7993
- function createBinding(name, type, refSection, aliased, property, excludeProperties, loc = null, refDeclared = false) {
8098
+ function createBinding(name, type, refSection, aliased, property, excludeProperties, loc = null, refDeclared = false, restOffset) {
7994
8099
  const id = getNextBindingId();
7995
8100
  const section = aliased ? aliased.section : refSection;
7996
8101
  const sameSection = refSection === section;
@@ -8009,6 +8114,7 @@ function createBinding(name, type, refSection, aliased, property, excludePropert
8009
8114
  closureId: void 0,
8010
8115
  assignments: void 0,
8011
8116
  excludeProperties,
8117
+ assignedProperties: void 0,
8012
8118
  sources: void 0,
8013
8119
  intersection: void 0,
8014
8120
  derivedFrom: void 0,
@@ -8022,11 +8128,11 @@ function createBinding(name, type, refSection, aliased, property, excludePropert
8022
8128
  declaredAlias: void 0,
8023
8129
  localOf: void 0,
8024
8130
  localClosures: void 0,
8025
- restOffset: void 0,
8131
+ restOffset,
8026
8132
  returnedBy: void 0,
8027
8133
  reserveSize: 0,
8028
8134
  scopeAccessor: void 0,
8029
- nullable: !sameSection || excludeProperties === void 0,
8135
+ nullable: !sameSection || excludeProperties === void 0 && restOffset === void 0,
8030
8136
  pruned: void 0,
8031
8137
  exposed: false,
8032
8138
  hasLazyReads: false
@@ -8053,6 +8159,18 @@ function getOrCreatePropertyAlias(binding, property) {
8053
8159
  while (isDirectAlias(binding)) binding = binding.aliasOf;
8054
8160
  return binding.propertyAliases.get(property) || createBinding(`${binding.name}_${property.replace(/[^a-zA-Z0-9_$]/g, "_")}`, binding.type, binding.section, binding, property);
8055
8161
  }
8162
+ function addAssignedProperty(binding, property) {
8163
+ if (binding.assignedProperties !== true) binding.assignedProperties = property === void 0 || propsUtil.add(binding.assignedProperties, property);
8164
+ }
8165
+ function getAssignedObject(binding) {
8166
+ let object;
8167
+ for (let alias = binding; alias.aliasOf && !isRest(alias); alias = alias.aliasOf) if (alias.property !== void 0) {
8168
+ let parent = alias.aliasOf;
8169
+ while (isDirectAlias(parent)) parent = parent.aliasOf;
8170
+ if (parent.assignedProperties === true || propsUtil.has(parent.assignedProperties, alias.property)) object = alias.aliasOf;
8171
+ }
8172
+ return object;
8173
+ }
8056
8174
  function getPropertyAlias(binding, properties) {
8057
8175
  return reduce(properties, getExistingPropertyAlias, binding);
8058
8176
  }
@@ -8111,12 +8229,15 @@ function getNearestDeclared(binding) {
8111
8229
  for (let cur = binding; cur; cur = cur.aliasOf) if (cur.declared) return cur;
8112
8230
  }
8113
8231
  function isDirectAlias(binding) {
8114
- return binding.aliasOf !== void 0 && binding.property === void 0 && binding.excludeProperties === void 0;
8232
+ return binding.aliasOf !== void 0 && binding.property === void 0 && !isRest(binding);
8233
+ }
8234
+ function isRest(binding) {
8235
+ return binding.excludeProperties !== void 0 || binding.restOffset !== void 0;
8115
8236
  }
8116
8237
  function getDebugScopeAccess(binding) {
8117
8238
  let root = binding;
8118
8239
  let access = "";
8119
- while (!(root.loc || root.declared) && root.aliasOf && root.excludeProperties === void 0) {
8240
+ while (!(root.loc || root.declared) && root.aliasOf && !isRest(root)) {
8120
8241
  if (root.property !== void 0) access = toAccess(root.property) + access;
8121
8242
  root = root.aliasOf;
8122
8243
  }
@@ -8132,7 +8253,7 @@ function getDebugName(binding) {
8132
8253
  if (isTemplateParam(binding)) {
8133
8254
  let root = binding;
8134
8255
  let access = "";
8135
- while (root.aliasOf !== root.section.params && root.excludeProperties === void 0) {
8256
+ while (root.aliasOf !== root.section.params && !isRest(root)) {
8136
8257
  if (root.property !== void 0) access = toAccess(root.property) + access;
8137
8258
  root = root.aliasOf;
8138
8259
  }
@@ -8150,11 +8271,11 @@ function getDebugNamesAsIdentifier(refs) {
8150
8271
  function getDebugNameAsIdentifier(binding) {
8151
8272
  let root = binding;
8152
8273
  let access = "";
8153
- if (isTemplateParam(binding)) while (root.aliasOf !== root.section.params && root.excludeProperties === void 0) {
8274
+ if (isTemplateParam(binding)) while (root.aliasOf !== root.section.params && !isRest(root)) {
8154
8275
  if (root.property !== void 0) access = `_${root.property.replace(/[^a-z0-9_$]/gi, "_") + access}`;
8155
8276
  root = root.aliasOf;
8156
8277
  }
8157
- else while (!(root.loc || root.declared) && root.aliasOf && root.excludeProperties === void 0) {
8278
+ else while (!(root.loc || root.declared) && root.aliasOf && !isRest(root)) {
8158
8279
  if (root.property !== void 0) access = `_${root.property.replace(/[^a-z0-9_$]/gi, "_") + access}`;
8159
8280
  root = root.aliasOf;
8160
8281
  }
@@ -8164,7 +8285,7 @@ function isInvokeOnlyBinding(binding) {
8164
8285
  return !someAlias(binding, isReadBeyondInvoking, void 0);
8165
8286
  }
8166
8287
  function isReadBeyondInvoking(binding) {
8167
- if (binding.assignments || binding.hoists || binding.getters.size || binding.propertyAliases.size || binding.excludeProperties) return true;
8288
+ if (binding.assignments || binding.hoists || binding.getters.size || binding.propertyAliases.size || isRest(binding)) return true;
8168
8289
  for (const expr of binding.reads.keys()) if (!expr.invokeOnly) return true;
8169
8290
  return false;
8170
8291
  }
@@ -9878,9 +9999,11 @@ var referenced_identifier_default = {
9878
9999
  const { name } = identifier.node;
9879
10000
  if (identifier.scope.hasBinding(name)) return;
9880
10001
  if (name === "$global") {
10002
+ assertReferencedInRender(identifier, name);
9881
10003
  setReferencesScope(identifier);
9882
10004
  trackGlobalReference(identifier);
9883
10005
  } else if (name === "$signal") {
10006
+ assertReferencedInRender(identifier, name);
9884
10007
  const section = getOrCreateSection(identifier);
9885
10008
  section.hasAbortSignal = true;
9886
10009
  setReferencesScope(identifier);
@@ -10063,7 +10186,7 @@ var native_tag_default = {
10063
10186
  } else {
10064
10187
  assertValidNativeEventHandlerAttr(tag, attr);
10065
10188
  if (isChangeHandlerAttr) valueExtra.retained = true;
10066
- if (!evaluate(attr.value).confident) {
10189
+ if (!isStaticDelimitedAttr(tag, attr) && !evaluate(attr.value).confident) {
10067
10190
  hasDynamicAttributes = true;
10068
10191
  addSetupExpr(tagSection, attr.value);
10069
10192
  } else if (attr.name === "content" && tagName !== "meta") addSetupExpr(tagSection, attr.value);
@@ -10137,13 +10260,21 @@ var native_tag_default = {
10137
10260
  const { confident, computed } = evaluate(value);
10138
10261
  if (confident) write`${getStaticAttrMarkup(name, computed)}`;
10139
10262
  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)}`;
10263
+ const meta = trackDelimitedAttrValue(tag, name, value);
10264
+ const { staticParts } = meta;
10265
+ if (getDelimitedAttrItems(name, meta) && staticParts.length) {
10266
+ if (staticParts.every(isLiteralPart)) write`${getStaticAttrMarkup(name, staticParts)}`;
10267
+ else {
10268
+ write` class="`;
10269
+ for (let i = 0; i < staticParts.length; i++) {
10270
+ const part = staticParts[i];
10271
+ if (i) write` `;
10272
+ if (isLiteralPart(part)) write`${getHTMLRuntime().escapeDoubleQuotedAttrValue(part)}`;
10273
+ else writeModuleReadTo(tag, part);
10274
+ }
10275
+ write`"`;
10276
+ }
10277
+ }
10147
10278
  }
10148
10279
  }
10149
10280
  write`>`;
@@ -10245,7 +10376,7 @@ var native_tag_default = {
10245
10376
  write`${callRuntime("_attr_option_value", value)}`;
10246
10377
  continue;
10247
10378
  }
10248
- write`${confident ? getStaticAttrMarkup(name, computed) : factorAttrConditional(buildAttrExpression(name, value))}`;
10379
+ write`${confident ? getStaticAttrMarkup(name, computed) : factorAttrConditional(buildAttrExpression(tag, name, value))}`;
10249
10380
  }
10250
10381
  if (handlers) for (const index of handlers) addHTMLEffectCall(tagSection, getReferencedBindings(attributes[index].value.extra));
10251
10382
  const isOpenOnly = !!(tagDef && tagDef.parseOptions?.openTagOnly);
@@ -10332,37 +10463,27 @@ var native_tag_default = {
10332
10463
  const valueReferences = getReferencedBindings(value.extra);
10333
10464
  switch (name) {
10334
10465
  case "class":
10335
- case "style": {
10336
- const helper = `_attr_${name}`;
10466
+ case "style":
10337
10467
  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
- }
10468
+ const meta = trackDelimitedAttrValue(tag, name, value);
10469
+ const items = getDelimitedAttrItems(name, meta);
10470
+ const calls = [];
10471
+ const assert = buildClassTogglesAssert(meta);
10472
+ if (assert) calls.push(assert);
10473
+ if (!items) calls.push(callRuntime(`_attr_${name}`, createScopeReadExpression(nodeBinding), value));
10474
+ else {
10475
+ const single = [];
10476
+ for (const { key, value } of items) if (isLiteralPart(key) && !/\s/.test(key)) single.push({
10477
+ key,
10478
+ value
10479
+ });
10480
+ else calls.push(callRuntime("_attr_class_names", createScopeReadExpression(nodeBinding), toClassPartExpression(key), value));
10481
+ if (single.length === 1) calls.push(callRuntime(`_attr_${name}_item`, createScopeReadExpression(nodeBinding), _marko_compiler.types.stringLiteral(single[0].key), single[0].value));
10482
+ 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
10483
  }
10362
- if (stmt) addStatement("render", tagSection, valueReferences, stmt, true);
10484
+ for (const call of calls) addStatement("render", tagSection, valueReferences, _marko_compiler.types.expressionStatement(call), true);
10363
10485
  }
10364
10486
  break;
10365
- }
10366
10487
  default: if (confident) break;
10367
10488
  else addStatement("render", tagSection, valueReferences, _marko_compiler.types.expressionStatement(callRuntime("_attr", createScopeReadExpression(nodeBinding), _marko_compiler.types.stringLiteral(name), value)), true);
10368
10489
  }
@@ -10637,13 +10758,13 @@ function getStaticAttrMarkup(name, computed) {
10637
10758
  default: return getHTMLRuntime()._attr(name, computed);
10638
10759
  }
10639
10760
  }
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));
10761
+ function buildAttrExpression(tag, name, value) {
10762
+ if (value.type === "ConditionalExpression") return _marko_compiler.types.conditionalExpression(value.test, buildAttrExpression(tag, name, value.consequent), buildAttrExpression(tag, name, value.alternate));
10642
10763
  const { confident, computed } = evaluate(value);
10643
10764
  if (confident) return _marko_compiler.types.stringLiteral(getStaticAttrMarkup(name, computed));
10644
10765
  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);
10766
+ case "class": return buildClassAttrExpression(tag, value) || callRuntime("_attr_class", value);
10767
+ case "style": return buildStyleAttrAnd(value) || callRuntime("_attr_style", value);
10647
10768
  default: return buildLogicalAttr(name, value) || callRuntime("_attr", _marko_compiler.types.stringLiteral(name), value);
10648
10769
  }
10649
10770
  }
@@ -10677,105 +10798,198 @@ function buildLogicalAttr(name, value) {
10677
10798
  const attr = getHTMLRuntime()._attr(name, computed);
10678
10799
  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
10800
  }
10680
- function buildStringAttrAnd(name, value) {
10801
+ function buildStyleAttrAnd(value) {
10681
10802
  if (value.type === "LogicalExpression" && value.operator === "&&") {
10682
10803
  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(""));
10804
+ if (confident) return _marko_compiler.types.conditionalExpression(value.left, _marko_compiler.types.stringLiteral(getStaticAttrMarkup("style", computed)), _marko_compiler.types.stringLiteral(""));
10684
10805
  }
10685
10806
  }
10686
10807
  const MAX_PRECOMPUTED_CLASS_TOGGLES = 4;
10687
- function buildClassAttrExpression(value) {
10688
- if (value.type !== "ObjectExpression" && value.type !== "ArrayExpression") return;
10808
+ function buildClassAttrExpression(tag, value) {
10809
+ const meta = trackDelimitedAttrValue(tag, "class", value);
10810
+ if (meta.dynamic) return;
10811
+ const markup = buildClassMarkup(meta);
10812
+ const assert = markup && buildClassTogglesAssert(meta);
10813
+ return assert ? _marko_compiler.types.sequenceExpression([assert, markup]) : markup;
10814
+ }
10815
+ function buildClassMarkup({ staticParts, dynamicValues = [] }) {
10816
+ if (dynamicValues.length > MAX_PRECOMPUTED_CLASS_TOGGLES) {
10817
+ if (staticParts.length) return callRuntime("_attr_class", buildClassString(staticParts, dynamicValues));
10818
+ return;
10819
+ }
10820
+ const combos = [];
10821
+ for (let mask = 0; mask < 1 << dynamicValues.length; mask++) {
10822
+ const parts = [...staticParts];
10823
+ for (let i = 0; i < dynamicValues.length; i++) {
10824
+ const { key, alternate } = dynamicValues[i];
10825
+ const part = mask & 1 << i ? key : alternate;
10826
+ if (part) parts.push(part);
10827
+ }
10828
+ combos.push(parts);
10829
+ }
10830
+ if (combos.every((parts) => parts.every(isLiteralPart))) return buildPrecomputedClass(combos.map((parts) => getHTMLRuntime()._attr_class(parts.join(" "))), dynamicValues);
10831
+ const table = getHoistedClassMarkup(combos);
10832
+ return dynamicValues.length ? _marko_compiler.types.memberExpression(table, buildToggleIndex(dynamicValues), true) : table;
10833
+ }
10834
+ function buildPrecomputedClass(combos, toggles) {
10835
+ if (!toggles.length) return _marko_compiler.types.stringLiteral(combos[0]);
10836
+ if (toggles.length === 1) return _marko_compiler.types.conditionalExpression(toggles[0].value, _marko_compiler.types.stringLiteral(combos[1]), _marko_compiler.types.stringLiteral(combos[0]));
10837
+ const end = commonAttrPrefixEnd(combos);
10838
+ const table = generateUidIdentifier("class");
10839
+ (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));
10840
+ const lookup = _marko_compiler.types.memberExpression(_marko_compiler.types.cloneNode(table), buildToggleIndex(toggles), true);
10841
+ return normalizeStringExpression([combos[0].slice(0, end), lookup]);
10842
+ }
10843
+ const [getHoistedClassMarkups] = createProgramState(() => /* @__PURE__ */ new Map());
10844
+ function getHoistedClassMarkup(combos) {
10845
+ const key = JSON.stringify(combos);
10846
+ const hoisted = getHoistedClassMarkups();
10847
+ let id = hoisted.get(key);
10848
+ if (!id) {
10849
+ const markups = combos.map((parts) => parts.length ? callRuntime("_attr_class", buildClassString(parts, [])) : _marko_compiler.types.stringLiteral(""));
10850
+ hoisted.set(key, id = generateUidIdentifier("class"));
10851
+ (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));
10852
+ }
10853
+ return _marko_compiler.types.cloneNode(id);
10854
+ }
10855
+ function buildClassTogglesAssert({ staticParts, dynamicValues }) {
10856
+ if (isOptimize() || !dynamicValues || [...staticParts, ...dynamicValues.flatMap(({ key, alternate }) => [key, alternate])].every((part) => part === void 0 || isLiteralPart(part))) return;
10857
+ return callRuntime("_assert_class_toggles", buildClassString(staticParts, []), _marko_compiler.types.arrayExpression(dynamicValues.map(({ key, alternate }) => buildClassString(alternate ? [key, alternate] : [key], []))));
10858
+ }
10859
+ function buildToggleIndex(toggles) {
10860
+ let index = _marko_compiler.types.conditionalExpression(toggles[0].value, _marko_compiler.types.numericLiteral(1), _marko_compiler.types.numericLiteral(0));
10861
+ 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)));
10862
+ return index;
10863
+ }
10864
+ function buildClassString(parts, toggles) {
10865
+ const strs = [];
10866
+ for (let i = 0; i < parts.length; i++) {
10867
+ if (i) strs.push(" ");
10868
+ strs.push(toClassPartExpression(parts[i]));
10869
+ }
10870
+ for (const { key, value, alternate } of toggles) strs.push(_marko_compiler.types.conditionalExpression(value, toSpacedClassPart(key), toSpacedClassPart(alternate)));
10871
+ return normalizeStringExpression(strs) || _marko_compiler.types.stringLiteral("");
10872
+ }
10873
+ function toClassPartExpression(part) {
10874
+ return isLiteralPart(part) ? _marko_compiler.types.stringLiteral(part) : toModuleReadExpression(part);
10875
+ }
10876
+ function toSpacedClassPart(part) {
10877
+ 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));
10878
+ }
10879
+ const delimitedAttrStringify = {
10880
+ class: [" ", stringifyClassObject],
10881
+ style: [";", stringifyStyleObject]
10882
+ };
10883
+ function assertUniqueClassToggles(tag, attr, { staticParts, dynamicValues = [] }) {
10884
+ const written = new Set(staticParts.flatMap(getClassNames));
10885
+ for (const { key, alternate } of dynamicValues) {
10886
+ const names = /* @__PURE__ */ new Set([...getClassNames(key), ...getClassNames(alternate)]);
10887
+ 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);
10888
+ for (const name of names) written.add(name);
10889
+ }
10890
+ }
10891
+ function getClassNames(part) {
10892
+ return part === void 0 ? [] : isLiteralPart(part) ? part.split(/\s+/).filter(Boolean) : [part.join(".")];
10893
+ }
10894
+ function isStaticDelimitedAttr(tag, attr) {
10895
+ const { name, value } = attr;
10896
+ if (name !== "class" && name !== "style") return false;
10897
+ const meta = trackDelimitedAttrValue(tag, name, value);
10898
+ if (name === "class") assertUniqueClassToggles(tag, attr, meta);
10899
+ return !meta.dynamic && !meta.dynamicValues;
10900
+ }
10901
+ function getDelimitedAttrItems(name, { dynamic, dynamicValues }) {
10902
+ if (dynamic) return;
10903
+ const items = [];
10904
+ if (!dynamicValues) return items;
10905
+ const keys = /* @__PURE__ */ new Set();
10906
+ for (const { key, value, alternate } of dynamicValues) {
10907
+ if (alternate !== void 0 || name === "style" && (!isLiteralPart(key) || /\s/.test(key) || keys.size === keys.add(key).size)) return;
10908
+ items.push({
10909
+ key,
10910
+ value
10911
+ });
10912
+ }
10913
+ return items;
10914
+ }
10915
+ function isLiteralPart(part) {
10916
+ return typeof part === "string";
10917
+ }
10918
+ function trackDelimitedAttrValue(tag, name, value) {
10689
10919
  const meta = {
10690
- staticItems: void 0,
10691
- dynamicItems: void 0,
10920
+ dynamic: false,
10921
+ staticParts: [],
10692
10922
  dynamicValues: void 0
10693
10923
  };
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
- }
10924
+ trackDelimitedAttrItem(tag, name, value, meta);
10925
+ return meta;
10733
10926
  }
10734
- function trackDelimitedAttrArrayItems(arr, meta) {
10735
- for (const item of arr.elements) if (item) switch (item.type) {
10927
+ function trackDelimitedAttrItem(tag, name, item, meta) {
10928
+ switch (item.type) {
10736
10929
  case "ArrayExpression":
10737
- trackDelimitedAttrArrayItems(item, meta);
10738
- break;
10739
- case "ObjectExpression":
10740
- trackDelimitedAttrObjectProperties(item, meta);
10741
- break;
10930
+ for (const child of item.elements) if (child) trackDelimitedAttrItem(tag, name, child, meta);
10931
+ return;
10742
10932
  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
- }
10933
+ if (item.argument.type === "ArrayExpression") trackDelimitedAttrItem(tag, name, item.argument, meta);
10934
+ else meta.dynamic = true;
10935
+ return;
10936
+ case "ObjectExpression":
10937
+ trackDelimitedAttrObjectProperties(tag, name, item, meta);
10938
+ return;
10752
10939
  }
10753
- }
10754
- function trackDelimitedAttrObjectProperties(obj, meta) {
10755
- let staticProps;
10756
- let dynamicProps;
10940
+ const part = getDelimitedAttrPart(tag, name, item);
10941
+ if (part !== void 0) {
10942
+ if (part) meta.staticParts.push(part);
10943
+ } else if (name === "class" && item.type === "LogicalExpression") {
10944
+ const key = item.operator === "&&" && getDelimitedAttrPart(tag, name, item.right);
10945
+ if (key) addDynamicValue(meta, key, item.left, void 0);
10946
+ else meta.dynamic = true;
10947
+ } else if (name === "class" && item.type === "ConditionalExpression") {
10948
+ const key = getDelimitedAttrPart(tag, name, item.consequent);
10949
+ const alternate = getDelimitedAttrPart(tag, name, item.alternate);
10950
+ if (key && alternate !== void 0) addDynamicValue(meta, key, item.test, alternate || void 0);
10951
+ else meta.dynamic = true;
10952
+ } else meta.dynamic = true;
10953
+ }
10954
+ function trackDelimitedAttrObjectProperties(tag, name, obj, meta) {
10757
10955
  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
- }
10956
+ const key = prop.type === "ObjectProperty" ? getDelimitedAttrKey(tag, name, prop) : void 0;
10957
+ if (!key || prop.type !== "ObjectProperty") {
10958
+ meta.dynamic = true;
10959
+ return;
10771
10960
  }
10772
10961
  const value = prop.value;
10773
- const propEval = evaluate(value);
10774
- if (propEval.confident) (staticProps ||= {})[key] = propEval.computed;
10775
- else (meta.dynamicValues ||= {})[key] = value;
10962
+ const { confident, computed } = evaluate(value);
10963
+ if (!confident) addDynamicValue(meta, key, value, void 0);
10964
+ else if (!isLiteralPart(key)) {
10965
+ if (computed) meta.staticParts.push(key);
10966
+ } else {
10967
+ const part = delimitedAttrStringify[name][1](key, computed);
10968
+ if (part) meta.staticParts.push(part);
10969
+ }
10776
10970
  }
10777
- if (staticProps) (meta.staticItems ||= []).push(staticProps);
10778
- if (dynamicProps) (meta.dynamicItems ||= []).push(_marko_compiler.types.objectExpression(dynamicProps));
10971
+ }
10972
+ function getDelimitedAttrKey(tag, name, prop) {
10973
+ if (!prop.computed && prop.key.type === "Identifier") return prop.key.name;
10974
+ const key = prop.key;
10975
+ const { confident, computed } = evaluate(key);
10976
+ if (confident) return typeof computed === "string" || typeof computed === "number" ? computed + "" : void 0;
10977
+ if (name === "class") return getStyleImportRead(tag, key);
10978
+ }
10979
+ function getDelimitedAttrPart(tag, name, value) {
10980
+ const { confident, computed } = evaluate(value);
10981
+ if (confident) {
10982
+ const [delimiter, stringify] = delimitedAttrStringify[name];
10983
+ return toDelimitedString(computed, delimiter, stringify);
10984
+ }
10985
+ if (name === "class") return getStyleImportRead(tag, value);
10986
+ }
10987
+ function addDynamicValue(meta, key, value, alternate) {
10988
+ (meta.dynamicValues ||= []).push({
10989
+ key,
10990
+ value,
10991
+ alternate
10992
+ });
10779
10993
  }
10780
10994
  function buildUndefined() {
10781
10995
  return _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0));
@@ -10826,7 +11040,7 @@ var dynamic_tag_default = {
10826
11040
  const { node } = tag;
10827
11041
  const definedBodySection = node.extra?.defineBodySection;
10828
11042
  if (definedBodySection) {
10829
- knownTagAnalyze(tag, definedBodySection, definedBodySection.params && getBindingPropTree(definedBodySection.params, !isSameOrChildSection(definedBodySection, getOrCreateSection(tag))));
11043
+ knownTagAnalyze(tag, definedBodySection);
10830
11044
  child(tag, getStaticTagName(tag.node), {
10831
11045
  kind: SectionRef,
10832
11046
  section: definedBodySection