marko 6.3.51 → 6.3.53

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/dist/debug/dom/catch.feat.js +1 -1
  2. package/dist/debug/dom/catch.feat.mjs +1 -1
  3. package/dist/debug/dom/controllable-input.feat.js +1 -1
  4. package/dist/debug/dom/controllable-input.feat.mjs +1 -1
  5. package/dist/debug/dom/controllable-open.feat.js +1 -1
  6. package/dist/debug/dom/controllable-open.feat.mjs +1 -1
  7. package/dist/debug/dom/controllable-select.feat.js +1 -1
  8. package/dist/debug/dom/controllable-select.feat.mjs +1 -1
  9. package/dist/debug/dom/controllable-textarea.feat.js +1 -1
  10. package/dist/debug/dom/controllable-textarea.feat.mjs +1 -1
  11. package/dist/debug/dom/controllable.feat.js +1 -1
  12. package/dist/debug/dom/controllable.feat.mjs +1 -1
  13. package/dist/debug/dom/dynamic-tag-script.feat.js +5 -0
  14. package/dist/debug/dom/dynamic-tag-script.feat.mjs +4 -0
  15. package/dist/debug/dom/dynamic-tag-var.feat.js +2 -4
  16. package/dist/debug/dom/dynamic-tag-var.feat.mjs +2 -4
  17. package/dist/debug/dom/placeholder.feat.js +2 -2
  18. package/dist/debug/dom/placeholder.feat.mjs +2 -2
  19. package/dist/debug/{dom-BAGeiafn.js → dom-CBLlE8L-.js} +46 -34
  20. package/dist/debug/{dom-C55iHvof.mjs → dom-DQCODUa1.mjs} +29 -23
  21. package/dist/debug/dom.js +11 -11
  22. package/dist/debug/dom.mjs +10 -10
  23. package/dist/debug/html.js +57 -41
  24. package/dist/debug/html.mjs +57 -41
  25. package/dist/dom/catch.feat.js +1 -1
  26. package/dist/dom/catch.feat.mjs +1 -1
  27. package/dist/dom/control-flow.d.ts +1 -3
  28. package/dist/dom/controllable-input.feat.js +1 -1
  29. package/dist/dom/controllable-input.feat.mjs +1 -1
  30. package/dist/dom/controllable-open.feat.js +1 -1
  31. package/dist/dom/controllable-open.feat.mjs +1 -1
  32. package/dist/dom/controllable-select.feat.js +1 -1
  33. package/dist/dom/controllable-select.feat.mjs +1 -1
  34. package/dist/dom/controllable-textarea.feat.js +1 -1
  35. package/dist/dom/controllable-textarea.feat.mjs +1 -1
  36. package/dist/dom/controllable.feat.js +1 -1
  37. package/dist/dom/controllable.feat.mjs +1 -1
  38. package/dist/dom/dynamic-tag-script.feat.d.ts +1 -0
  39. package/dist/dom/dynamic-tag-script.feat.js +4 -0
  40. package/dist/dom/dynamic-tag-script.feat.mjs +4 -0
  41. package/dist/dom/dynamic-tag-var.feat.js +2 -2
  42. package/dist/dom/dynamic-tag-var.feat.mjs +3 -3
  43. package/dist/dom/placeholder.feat.js +2 -2
  44. package/dist/dom/placeholder.feat.mjs +2 -2
  45. package/dist/dom/resume.d.ts +2 -2
  46. package/dist/{dom-BNmfm4st.js → dom-vuB05Hnj.js} +37 -30
  47. package/dist/{dom-BsAS26Ze.mjs → dom-z4IMlmeO.mjs} +21 -19
  48. package/dist/dom.d.ts +2 -2
  49. package/dist/dom.js +15 -15
  50. package/dist/dom.mjs +10 -10
  51. package/dist/html/template.d.ts +3 -1
  52. package/dist/html/writer.d.ts +6 -1
  53. package/dist/html.js +41 -26
  54. package/dist/html.mjs +41 -26
  55. package/dist/translator/core/await.d.ts +0 -7
  56. package/dist/translator/core/try.d.ts +0 -7
  57. package/dist/translator/index.d.ts +1 -1
  58. package/dist/translator/index.js +830 -596
  59. package/dist/translator/util/binding-has-prop.d.ts +1 -1
  60. package/dist/translator/util/cyclic-memo.d.ts +4 -0
  61. package/dist/translator/util/evaluate.d.ts +2 -0
  62. package/dist/translator/util/optional.d.ts +21 -7
  63. package/dist/translator/util/references.d.ts +58 -23
  64. package/dist/translator/util/runtime.d.ts +3 -1
  65. package/dist/translator/util/sections.d.ts +8 -11
  66. package/dist/translator/util/serialize-guard.d.ts +4 -0
  67. package/dist/translator/util/serialize-reasons.d.ts +10 -11
  68. package/dist/translator/util/set-tag-sections-downstream.d.ts +3 -2
  69. package/dist/translator/util/tag-name-type.d.ts +8 -3
  70. package/dist/translator/visitors/tag/dynamic-tag.d.ts +0 -2
  71. package/index.d.ts +0 -5
  72. package/package.json +4 -4
  73. package/tags-html.d.ts +2 -0
@@ -204,6 +204,58 @@ const Subscriptions$1 = "#Subscriptions";
204
204
  const TagVariable$1 = "#TagVariable";
205
205
  const TagVariableChange$2 = "#TagVariableChange";
206
206
  //#endregion
207
+ //#region src/translator/util/traverse.ts
208
+ const skip = Symbol("skip");
209
+ function traverseReplace(container, key, enter, state) {
210
+ const node = container[key];
211
+ if (node) if (Array.isArray(node)) for (let i = node.length; i--;) traverseReplace(node, i, enter, state);
212
+ else {
213
+ const keys = _marko_compiler.types.VISITOR_KEYS[node.type];
214
+ for (let i = keys.length; i--;) traverseReplace(node, keys[i], enter, state);
215
+ const replacement = enter(node, state);
216
+ if (replacement) container[key] = replacement;
217
+ }
218
+ }
219
+ function traverseContains(node, check) {
220
+ return !!traverseFind(node, check);
221
+ }
222
+ function traverseFind(node, check) {
223
+ if (node) if (Array.isArray(node)) for (const item of node) {
224
+ const found = traverseFind(item, check);
225
+ if (found) return found;
226
+ }
227
+ else {
228
+ switch (check(node)) {
229
+ case true: return node;
230
+ case skip: return;
231
+ }
232
+ for (const key of _marko_compiler.types.VISITOR_KEYS[node.type]) {
233
+ const found = traverseFind(node[key], check);
234
+ if (found) return found;
235
+ }
236
+ }
237
+ }
238
+ function traverseFindAwait(node) {
239
+ return traverseFind(node, (child) => {
240
+ switch (child.type) {
241
+ case "ForOfStatement": return child.await;
242
+ case "FunctionDeclaration":
243
+ case "FunctionExpression":
244
+ case "ArrowFunctionExpression":
245
+ case "ClassMethod":
246
+ case "ObjectMethod":
247
+ case "ClassPrivateMethod": return skip;
248
+ case "AwaitExpression": return true;
249
+ }
250
+ });
251
+ }
252
+ function traverse(visit, node, parent, grandParent) {
253
+ if (node) {
254
+ if (Array.isArray(node)) for (const item of node) traverse(visit, item, parent, grandParent);
255
+ else if (visit(node, parent, grandParent) !== skip) for (const key of _marko_compiler.types.VISITOR_KEYS[node.type]) traverse(visit, node[key], node, parent);
256
+ }
257
+ }
258
+ //#endregion
207
259
  //#region src/translator/util/evaluate.ts
208
260
  function evaluate(value) {
209
261
  let { extra } = value;
@@ -214,14 +266,36 @@ function evaluate(value) {
214
266
  extra.computed = computed.value;
215
267
  extra.confident = true;
216
268
  extra.nullable = computed.value == null;
269
+ extra.pure = true;
217
270
  } else {
218
271
  extra.computed = void 0;
219
272
  extra.confident = false;
220
273
  extra.nullable = isNullableExpr(value);
274
+ extra.pure = !traverseContains(value, isImpure);
221
275
  }
222
276
  }
223
277
  return extra;
224
278
  }
279
+ function isImpure(node) {
280
+ switch (node.type) {
281
+ case "ArrowFunctionExpression":
282
+ case "ClassPrivateMethod":
283
+ case "ClassPrivateProperty":
284
+ case "FunctionExpression": return skip;
285
+ case "ClassMethod":
286
+ case "ObjectMethod": return node.computed && traverseContains(node.key, isImpure) || skip;
287
+ case "ClassAccessorProperty":
288
+ case "ClassProperty": return node.static ? void 0 : node.computed && traverseContains(node.key, isImpure) || skip;
289
+ case "CallExpression": return node.callee.type === "ArrowFunctionExpression" || node.callee.type === "FunctionExpression" ? traverseContains(node.arguments, isImpure) || traverseContains(node.callee.params, isImpure) || traverseContains(node.callee.body, isImpure) || skip : true;
290
+ case "AssignmentExpression":
291
+ case "NewExpression":
292
+ case "OptionalCallExpression":
293
+ case "TaggedTemplateExpression":
294
+ case "ThrowStatement":
295
+ case "UpdateExpression": return true;
296
+ case "UnaryExpression": return node.operator === "delete";
297
+ }
298
+ }
225
299
  function isNullableExpr(expr) {
226
300
  switch (expr.type) {
227
301
  case "ArrayExpression":
@@ -392,58 +466,6 @@ function getCompileStage(file = (0, _marko_compiler_babel_utils.getFile)()) {
392
466
  return file.___compileStage;
393
467
  }
394
468
  //#endregion
395
- //#region src/translator/util/traverse.ts
396
- const skip = Symbol("skip");
397
- function traverseReplace(container, key, enter, state) {
398
- const node = container[key];
399
- if (node) if (Array.isArray(node)) for (let i = node.length; i--;) traverseReplace(node, i, enter, state);
400
- else {
401
- const keys = _marko_compiler.types.VISITOR_KEYS[node.type];
402
- for (let i = keys.length; i--;) traverseReplace(node, keys[i], enter, state);
403
- const replacement = enter(node, state);
404
- if (replacement) container[key] = replacement;
405
- }
406
- }
407
- function traverseContains(node, check) {
408
- return !!traverseFind(node, check);
409
- }
410
- function traverseFind(node, check) {
411
- if (node) if (Array.isArray(node)) for (const item of node) {
412
- const found = traverseFind(item, check);
413
- if (found) return found;
414
- }
415
- else {
416
- switch (check(node)) {
417
- case true: return node;
418
- case skip: return;
419
- }
420
- for (const key of _marko_compiler.types.VISITOR_KEYS[node.type]) {
421
- const found = traverseFind(node[key], check);
422
- if (found) return found;
423
- }
424
- }
425
- }
426
- function traverseFindAwait(node) {
427
- return traverseFind(node, (child) => {
428
- switch (child.type) {
429
- case "ForOfStatement": return child.await;
430
- case "FunctionDeclaration":
431
- case "FunctionExpression":
432
- case "ArrowFunctionExpression":
433
- case "ClassMethod":
434
- case "ObjectMethod":
435
- case "ClassPrivateMethod": return skip;
436
- case "AwaitExpression": return true;
437
- }
438
- });
439
- }
440
- function traverse(visit, node, parent, grandParent) {
441
- if (node) {
442
- if (Array.isArray(node)) for (const item of node) traverse(visit, item, parent, grandParent);
443
- else if (visit(node, parent, grandParent) !== skip) for (const key of _marko_compiler.types.VISITOR_KEYS[node.type]) traverse(visit, node[key], node, parent);
444
- }
445
- }
446
- //#endregion
447
469
  //#region src/translator/util/generate-uid.ts
448
470
  const countsForFile = /* @__PURE__ */ new WeakMap();
449
471
  function generateUid(name = "") {
@@ -703,6 +725,9 @@ var Sorted = class {
703
725
  }
704
726
  return b;
705
727
  }
728
+ filter(data, cb) {
729
+ return filter(data, cb);
730
+ }
706
731
  find(data, item) {
707
732
  if (data !== void 0) {
708
733
  if (Array.isArray(data)) return findSorted(this.compare, data, item);
@@ -757,6 +782,9 @@ function concat(a, b) {
757
782
  }
758
783
  return b;
759
784
  }
785
+ function size(data) {
786
+ return data !== void 0 ? Array.isArray(data) ? data.length : 1 : 0;
787
+ }
760
788
  function filter(data, cb) {
761
789
  if (data !== void 0) {
762
790
  if (Array.isArray(data)) {
@@ -816,6 +844,12 @@ function find(data, cb) {
816
844
  function some(data, cb) {
817
845
  return data !== void 0 ? Array.isArray(data) ? data.some(cb) : !!cb(data, 0) : false;
818
846
  }
847
+ function every(data, cb) {
848
+ return data !== void 0 ? Array.isArray(data) ? data.every(cb) : !!cb(data, 0) : true;
849
+ }
850
+ function reduce(data, cb, initial) {
851
+ return data !== void 0 ? Array.isArray(data) ? data.reduce(cb, initial) : cb(initial, data, 0) : initial;
852
+ }
819
853
  function toArray(data, cb) {
820
854
  return data !== void 0 ? Array.isArray(data) ? data.map(cb) : [cb(data, 0)] : [];
821
855
  }
@@ -914,6 +948,18 @@ function joinRepeatable(compare, a, b) {
914
948
  const compareResult = compare(a, b);
915
949
  return compareResult === 0 ? a : compareResult < 0 ? [a, b] : [b, a];
916
950
  }
951
+ function addUnique(data, item) {
952
+ return includes(data, item) ? data : push(data, item);
953
+ }
954
+ function at(data, index) {
955
+ return Array.isArray(data) ? data[index] : index ? void 0 : data;
956
+ }
957
+ function first(data) {
958
+ return Array.isArray(data) ? data[0] : data;
959
+ }
960
+ function rest(data) {
961
+ return Array.isArray(data) ? data.length === 2 ? data[1] : data.slice(1) : void 0;
962
+ }
917
963
  //#endregion
918
964
  //#region src/common/constants/accessor-prefix.ts
919
965
  var accessor_prefix_exports = /* @__PURE__ */ __exportAll({
@@ -996,124 +1042,89 @@ function getAccessorProp() {
996
1042
  //#region src/translator/util/serialize-reasons.ts
997
1043
  const sourcesUtil = new Sorted(compareSources);
998
1044
  function isSameReason(a, b) {
999
- return a === b || (a && b ? a !== true && b !== true && compareSources(a, b) === 0 : false);
1045
+ return a === b || (a && b ? a.forced && b.forced || compareSources(a, b) === 0 : false);
1000
1046
  }
1001
1047
  function isForceSerialized(section, prop, prefix) {
1002
- return true === (prop ? section.serializeReasons.get(getPropKey(section, prop, prefix)) : section.serializeReason);
1048
+ return !!(prop ? section.serializeReasons.get(getPropKey(section, prop, prefix)) : section.serializeReason)?.forced;
1003
1049
  }
1004
1050
  function addSerializeReason(section, reason, prop, prefix) {
1005
1051
  if (reason) {
1006
- if (reason !== true) addProvenance(section, reason, prop && getPropKey(section, prop, prefix));
1007
- if (prop) {
1008
- const key = getPropKey(section, prop, prefix);
1052
+ const key = prop && getPropKey(section, prop, prefix);
1053
+ if (key) {
1009
1054
  const curReason = section.serializeReasons.get(key);
1010
- if (curReason !== true) if (reason === true) forcePropSerialize(section, key);
1011
- else {
1012
- const newReason = mergeSerializeReasons(curReason, reason);
1013
- if (curReason !== newReason) setPropSerializeReason(section, key, newReason);
1014
- }
1055
+ const newReason = mergeSerializeReasons(curReason, reason);
1056
+ if (curReason !== newReason) setPropSerializeReason(section, key, newReason);
1015
1057
  } else {
1016
1058
  const curReason = section.serializeReason;
1017
- if (curReason !== true) if (reason === true) forceSerialize(section);
1018
- else {
1019
- const newReason = mergeSerializeReasons(curReason, reason);
1020
- if (curReason !== newReason) setSerializeReason(section, newReason);
1021
- }
1059
+ const newReason = mergeSerializeReasons(curReason, reason);
1060
+ if (curReason !== newReason) setSerializeReason(section, newReason);
1022
1061
  }
1023
1062
  }
1024
1063
  }
1025
1064
  function addSerializeExpr(section, expr, prop, prefix) {
1026
1065
  if (expr) if (prop) {
1027
1066
  const key = getPropKey(section, prop, prefix);
1028
- if (expr === true) {
1029
- if (section.serializeReasons.get(key) !== true) forcePropSerialize(section, key);
1030
- } else {
1031
- const curExprs = section.propSerializeExprs ??= /* @__PURE__ */ new Map();
1032
- const curExpr = curExprs.get(key);
1033
- curExprs.set(key, curExpr ? concat(curExpr, expr) : expr);
1034
- }
1035
- } else if (expr === true) {
1036
- if (section.serializeReason !== true) forceSerialize(section);
1067
+ const curExprs = section.propSerializeExprs ??= /* @__PURE__ */ new Map();
1068
+ const curExpr = curExprs.get(key);
1069
+ curExprs.set(key, curExpr ? concat(curExpr, expr) : expr);
1037
1070
  } else {
1038
1071
  const curExpr = section.serializeExprs;
1039
1072
  section.serializeExprs = curExpr ? concat(curExpr, expr) : expr;
1040
1073
  }
1041
1074
  }
1042
1075
  function addOwnerSerializeReason(from, to, reason) {
1043
- if (reason) {
1044
- let cur = from;
1045
- while (cur !== to && cur.parent) {
1046
- addSerializeReason(cur, reason, getAccessorProp().Owner);
1047
- cur = cur.parent;
1048
- }
1049
- }
1076
+ if (reason) for (const section of ancestorSections(from, to)) addSerializeReason(section, reason, getAccessorProp().Owner);
1050
1077
  }
1051
1078
  function isReasonDynamic(reason) {
1052
- return !!reason && reason !== true && !reason.state;
1079
+ return !!reason && !reason.forced && !reason.state;
1053
1080
  }
1054
1081
  function isStaticSerializeReason(reason) {
1055
1082
  return !!reason && !isReasonDynamic(reason);
1056
1083
  }
1057
1084
  function isStateSerializeReason(reason) {
1058
- return !!reason && reason !== true && !!reason.state;
1085
+ return !!reason && !reason.forced && !!reason.state;
1059
1086
  }
1060
1087
  function getSerializeReason(section, prop, prefix) {
1061
1088
  if (prop) return section.serializeReasons.get(getPropKey(section, prop, prefix));
1062
1089
  else return section.serializeReason;
1063
1090
  }
1064
1091
  function getSerializeSourcesForExpr(expr) {
1065
- return isReferencedExtra(expr) ? getSerializeSourcesForRef(expr.referencedBindings) : void 0;
1092
+ const root = getCanonicalExtra(expr);
1093
+ return isReferencedExtra(root) ? getSerializeSourcesForRef(root.referencedBindings) : void 0;
1066
1094
  }
1067
1095
  function getSerializeSourcesForExprs(exprs) {
1068
- if (exprs) if (exprs === true) return exprs;
1069
- else if (Array.isArray(exprs)) {
1070
- let allSources;
1071
- for (const expr of exprs) allSources = mergeSources(allSources, getSerializeSourcesForExpr(expr));
1072
- return allSources;
1073
- } else return getSerializeSourcesForExpr(exprs);
1096
+ if (exprs) {
1097
+ if (exprs === true) return FORCED;
1098
+ return reduce(exprs, mergeExprSources);
1099
+ }
1074
1100
  }
1075
1101
  function getSerializeSourcesForRef(ref) {
1076
- if (ref) {
1077
- let allSources;
1078
- if (Array.isArray(ref)) {
1079
- for (const { sources } of ref) allSources = mergeSources(allSources, sources);
1080
- return allSources;
1081
- } else return ref.sources;
1082
- }
1102
+ return reduce(ref, mergeBindingSources);
1083
1103
  }
1084
- function mapCrossProgramReason(program, reason, exprs) {
1085
- let params;
1086
- let mapped;
1087
- let crossProgram = false;
1088
- forEach(reason.param, (param) => {
1089
- if (param.section.program === program) params = bindingUtil.add(params, param);
1090
- else {
1091
- crossProgram = true;
1092
- mapped = exprs ? mergeSerializeReasons(mapped, getSerializeSourcesForExprs(mapParamBindingToExpr(exprs, param))) : true;
1093
- }
1094
- });
1095
- if (!crossProgram) return reason;
1096
- return mergeRemappedSources(reason, params, mapped);
1104
+ function mergeExprSources(sources, expr) {
1105
+ return mergeSources(sources, getSerializeSourcesForExpr(expr));
1097
1106
  }
1098
- function mapDownstreamReason(program, reason, exprs) {
1107
+ function mergeBindingSources(sources, binding) {
1108
+ return mergeSources(sources, binding.sources);
1109
+ }
1110
+ function mapParamReason(program, reason, exprs, ownParams) {
1099
1111
  let params;
1100
1112
  let mapped;
1101
- let downstream = false;
1113
+ let any = false;
1102
1114
  forEach(reason.param, (param) => {
1103
- if (param.section.program === program) {
1104
- downstream = true;
1105
- mapped = mergeSerializeReasons(mapped, getSerializeSourcesForExprs(mapParamBindingToExpr(exprs, param)));
1115
+ if (param.section.program === program === ownParams) {
1116
+ any = true;
1117
+ mapped = exprs ? mergeSerializeReasons(mapped, getSerializeSourcesForExprs(mapParamBindingToExpr(exprs, param))) : FORCED;
1106
1118
  } else params = bindingUtil.add(params, param);
1107
1119
  });
1108
- if (!downstream) return reason;
1120
+ if (!any) return reason;
1109
1121
  return mergeRemappedSources(reason, params, mapped);
1110
1122
  }
1111
1123
  function mergeRemappedSources(reason, params, mapped) {
1112
- if (mapped !== true && (reason.state || reason.global || params)) mapped = mergeSerializeReasons(mapped, createSources(reason.state, params, reason.global));
1124
+ if (reason.state || reason.global || params || reason.forced) mapped = mergeSerializeReasons(mapped, createSources(reason.state, params, reason.global, reason.forced));
1113
1125
  return mapped;
1114
1126
  }
1115
1127
  function mergeSerializeReasons(a, b) {
1116
- if (a === true || b === true) return true;
1117
1128
  return mergeSources(a, b);
1118
1129
  }
1119
1130
  function applySerializeExprs(section) {
@@ -1121,11 +1132,10 @@ function applySerializeExprs(section) {
1121
1132
  if (propExprs) {
1122
1133
  section.propSerializeExprs = void 0;
1123
1134
  for (const [key, exprs] of propExprs) {
1124
- addProvenance(section, getProvenanceForExprs(exprs), key);
1125
- const exprReason = getSerializeSourcesForExprs(exprs);
1126
- if (exprReason) {
1135
+ const reason = getSerializeSourcesForExprs(exprs);
1136
+ if (reason) {
1127
1137
  const curReason = section.serializeReasons.get(key);
1128
- const newReason = mergeSerializeReasons(curReason, exprReason);
1138
+ const newReason = mergeSerializeReasons(curReason, reason);
1129
1139
  if (curReason !== newReason) setPropSerializeReason(section, key, newReason);
1130
1140
  }
1131
1141
  }
@@ -1133,52 +1143,23 @@ function applySerializeExprs(section) {
1133
1143
  const scopeExprs = section.serializeExprs;
1134
1144
  if (scopeExprs) {
1135
1145
  section.serializeExprs = void 0;
1136
- addProvenance(section, getProvenanceForExprs(scopeExprs));
1137
- const exprReason = getSerializeSourcesForExprs(scopeExprs);
1138
- if (exprReason) {
1146
+ const reason = getSerializeSourcesForExprs(scopeExprs);
1147
+ if (reason) {
1139
1148
  const curReason = section.serializeReason;
1140
- const newReason = mergeSerializeReasons(curReason, exprReason);
1149
+ const newReason = mergeSerializeReasons(curReason, reason);
1141
1150
  if (curReason !== newReason) setSerializeReason(section, newReason);
1142
1151
  }
1143
1152
  }
1144
1153
  }
1145
1154
  function finalizeSerializeReason(section) {
1146
- some(section.bindings, (binding) => {
1155
+ forEach(section.bindings, (binding) => {
1147
1156
  const reason = binding.type === 0 && getSerializeReason(section, binding);
1148
- if (reason) section.domSerializeReasons = reason === true ? true : sourcesUtil.add(section.domSerializeReasons, reason);
1149
- return reason === true;
1157
+ if (reason) section.domSerializeReasons = sourcesUtil.add(section.domSerializeReasons, reason);
1150
1158
  });
1151
1159
  const curReason = section.serializeReason;
1152
1160
  let newReason = curReason;
1153
- if (newReason !== true) {
1154
- for (const propReason of section.serializeReasons.values()) {
1155
- if (propReason === true) {
1156
- newReason = true;
1157
- break;
1158
- }
1159
- newReason = mergeSources(newReason, propReason);
1160
- }
1161
- if (newReason && curReason !== newReason) setSerializeReason(section, newReason);
1162
- }
1163
- const propProvenance = section.propSerializeProvenance;
1164
- if (propProvenance) for (const provenance of propProvenance.values()) addProvenance(section, provenance);
1165
- }
1166
- function addProvenance(section, sources, key) {
1167
- if (!sources) return;
1168
- if (key) {
1169
- const provenance = section.propSerializeProvenance ??= /* @__PURE__ */ new Map();
1170
- provenance.set(key, mergeSources(provenance.get(key), sources));
1171
- } else section.serializeProvenance = mergeSources(section.serializeProvenance, sources);
1172
- }
1173
- function getProvenanceForExprs(exprs) {
1174
- let sources;
1175
- forEach(exprs, (expr) => {
1176
- sources = mergeSources(sources, getSerializeSourcesForExpr(expr));
1177
- forEach(expr.referencedBindingsInFunction, (binding) => {
1178
- sources = mergeSources(sources, getSerializeSourcesForRef(binding));
1179
- });
1180
- });
1181
- return sources;
1161
+ for (const propReason of section.serializeReasons.values()) newReason = mergeSources(newReason, propReason);
1162
+ if (newReason && curReason !== newReason) setSerializeReason(section, newReason);
1182
1163
  }
1183
1164
  function getPropKey(section, prop, prefix) {
1184
1165
  if (isStrOrSym(prop)) {
@@ -1195,12 +1176,6 @@ function getPropKey(section, prop, prefix) {
1195
1176
  return key;
1196
1177
  }
1197
1178
  }
1198
- function forceSerialize(section) {
1199
- setSerializeReason(section, true);
1200
- }
1201
- function forcePropSerialize(section, key) {
1202
- setPropSerializeReason(section, key, true);
1203
- }
1204
1179
  function isStrOrSym(v) {
1205
1180
  switch (typeof v) {
1206
1181
  case "string":
@@ -1284,6 +1259,7 @@ function analyzeExpressionTagName(name, extra) {
1284
1259
  let nullable = false;
1285
1260
  let tagNameImported;
1286
1261
  let tagNameLoad;
1262
+ let tagNameTemplates = [];
1287
1263
  while ((path = pending.pop()) && type !== 2) {
1288
1264
  if (seen.has(path.node)) continue;
1289
1265
  seen.add(path.node);
@@ -1312,6 +1288,12 @@ function analyzeExpressionTagName(name, extra) {
1312
1288
  const decl = binding.path.parent;
1313
1289
  if (MARKO_FILE_REG.test(decl.source.value) && decl.specifiers.some((it) => _marko_compiler.types.isImportDefaultSpecifier(it))) {
1314
1290
  const resolvedImport = decl.extra?.tagImport || decl.source.value;
1291
+ if (tagNameTemplates) {
1292
+ const childFile = (0, _marko_compiler_babel_utils.loadFileForImport)((0, _marko_compiler_babel_utils.getFile)(), resolvedImport);
1293
+ const childExtra = childFile?.ast.program.extra;
1294
+ if (!childExtra || isAnalyzing(childFile)) tagNameTemplates = void 0;
1295
+ else if (!tagNameTemplates.includes(childExtra)) tagNameTemplates.push(childExtra);
1296
+ }
1315
1297
  if (type === void 0) {
1316
1298
  type = 1;
1317
1299
  tagNameImported = resolvedImport;
@@ -1341,9 +1323,12 @@ function analyzeExpressionTagName(name, extra) {
1341
1323
  }
1342
1324
  extra.tagNameType = type ?? 2;
1343
1325
  extra.tagNameNullable = nullable;
1344
- if (type === 1 && tagNameImported) {
1345
- extra.tagNameImported = tagNameImported;
1346
- extra.tagNameLoad = tagNameLoad;
1326
+ if (type === 1) {
1327
+ extra.tagNameTemplates = tagNameTemplates;
1328
+ if (tagNameImported) {
1329
+ extra.tagNameImported = tagNameImported;
1330
+ extra.tagNameLoad = tagNameLoad;
1331
+ }
1347
1332
  }
1348
1333
  }
1349
1334
  //#endregion
@@ -1381,8 +1366,6 @@ function startSection(path) {
1381
1366
  domSerializeReasons: void 0,
1382
1367
  serializeExprs: void 0,
1383
1368
  propSerializeExprs: void 0,
1384
- serializeProvenance: void 0,
1385
- propSerializeProvenance: void 0,
1386
1369
  serializePropKeys: void 0,
1387
1370
  paramReasonGroups: void 0,
1388
1371
  returnValueExpr: void 0,
@@ -1424,6 +1407,9 @@ function forEachSection(fn) {
1424
1407
  const { sections } = (0, _marko_compiler_babel_utils.getProgram)().node.extra;
1425
1408
  sections?.forEach(fn);
1426
1409
  }
1410
+ function* ancestorSections(from, to) {
1411
+ for (let cur = from; cur !== to && cur.parent; cur = cur.parent) yield cur;
1412
+ }
1427
1413
  function forEachSectionReverse(fn) {
1428
1414
  const { sections } = (0, _marko_compiler_babel_utils.getProgram)().node.extra;
1429
1415
  for (let i = sections.length; i--;) fn(sections[i]);
@@ -1498,10 +1484,13 @@ function getNodeContentType(path, extraMember, contentInfo) {
1498
1484
  }
1499
1485
  function getSectionRegisterReasons(section) {
1500
1486
  if (section.isBranch) return false;
1487
+ if (section.upstreamExpression?.tagNameType === 0) return false;
1501
1488
  const { downstream } = section;
1502
1489
  if (downstream?.binding) {
1503
- let downstreamReasons = getAllSerializeReasonsForBinding(downstream.binding, downstream.properties);
1504
- if (downstreamReasons && downstreamReasons !== true) downstreamReasons = mapCrossProgramReason(section.program, downstreamReasons, downstream.exprs);
1490
+ const downstreamReasons = reduce(downstream.binding, (reasons, binding) => {
1491
+ const reason = getAllSerializeReasonsForBinding(binding, downstream.properties);
1492
+ return mergeSerializeReasons(reasons, reason && (downstream.exprs ? mapParamReason(binding.section.program, reason, downstream.exprs, true) : mapParamReason(section.program, reason, void 0, false)));
1493
+ });
1505
1494
  if (!downstreamReasons) return false;
1506
1495
  if (isReasonDynamic(downstreamReasons) && !section.serializeReason && !section.serializeReasons.size && !section.parent?.serializeReason && !section.parent?.serializeReasons.size) return false;
1507
1496
  return downstreamReasons;
@@ -1527,7 +1516,7 @@ function getDynamicClosureIndex(closure, closureSection) {
1527
1516
  return index;
1528
1517
  }
1529
1518
  function getDirectClosures(section) {
1530
- if (section.isBranch) return filter(section.referencedClosures, (closure) => isImmediateOwner(section, closure));
1519
+ if (section.isBranch) return bindingUtil.filter(section.referencedClosures, (closure) => isImmediateOwner(section, closure));
1531
1520
  }
1532
1521
  function isSameOrChildSection(section, other) {
1533
1522
  do
@@ -1613,30 +1602,14 @@ var function_default = { analyze(fn) {
1613
1602
  const section = getSection(fn);
1614
1603
  const fnExtra = node.extra ??= {};
1615
1604
  fnExtra.section = section;
1605
+ fnExtra.exprRoot = exprRoot.node.extra ??= {};
1616
1606
  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");
1617
1607
  reserveExportRegisterId(fnExtra, fn, markoRoot);
1618
1608
  if (isStaticRoot(markoRoot)) {
1619
1609
  const refs = getStaticDeclRefs(fn);
1620
- if (refs === true) registerFunction(fnExtra, true);
1621
- else if (refs.size) getReferencesByFn().set(fnExtra, refs);
1622
- } else if (shouldAlwaysRegister(markoRoot)) registerFunction(fnExtra, true);
1623
- else {
1624
- const refs = /* @__PURE__ */ new Set([exprRoot.node.extra ??= {}]);
1625
- if (getConstTagVarRefs(markoRoot, refs) === true) registerFunction(fnExtra, true);
1626
- else getReferencesByFn().set(fnExtra, refs);
1627
- }
1610
+ if (refs.size) getReferencesByFn().set(fnExtra, refs);
1611
+ } else getReferencesByFn().set(fnExtra, /* @__PURE__ */ new Set([fnExtra.exprRoot]));
1628
1612
  } };
1629
- function getConstTagVarRefs(markoRoot, refs, seen = /* @__PURE__ */ new Set()) {
1630
- const tag = getTagFromMarkoRoot(markoRoot);
1631
- if (!tag?.node.var || !isCoreTagName(tag, "const") || seen.has(tag.node)) return refs;
1632
- seen.add(tag.node);
1633
- const ids = tag.get("var").getOuterBindingIdentifiers();
1634
- for (const name in ids) {
1635
- const binding = tag.scope.getBinding(name);
1636
- if (binding && addBindingRefs(binding, refs, seen) === true) return true;
1637
- }
1638
- return refs;
1639
- }
1640
1613
  function finalizeFunctionRegistry() {
1641
1614
  for (const [fnExtra, exprExtras] of getReferencesByFn()) {
1642
1615
  const reason = resolveSerializeReason(exprExtras);
@@ -1658,8 +1631,8 @@ function trackImportedFn(importDecl, local, resolved) {
1658
1631
  local
1659
1632
  };
1660
1633
  const refs = /* @__PURE__ */ new Set();
1661
- if (addBindingRefs(binding, refs, /* @__PURE__ */ new Set()) === true) registerImportedFn(importedFn);
1662
- else if (refs.size) getReferencesByImportedFn().set(importedFn, refs);
1634
+ addBindingRefs(binding, refs, /* @__PURE__ */ new Set());
1635
+ if (refs.size) getReferencesByImportedFn().set(importedFn, refs);
1663
1636
  }
1664
1637
  /**
1665
1638
  * Finds the id reserved for an export, following `export ... from` hops. Each
@@ -1695,7 +1668,7 @@ function resolveRegisteredExport(file, exportName, seen = /* @__PURE__ */ new Se
1695
1668
  }
1696
1669
  function resolveSerializeReason(exprExtras) {
1697
1670
  let reason;
1698
- for (const exprExtra of exprExtras) reason = mergeSerializeReasons(reason, getAllSerializeReasonsForExtra(getCanonicalExtra(exprExtra), true));
1671
+ for (const exprExtra of exprExtras) reason = mergeSerializeReasons(reason, getRegisterReasonForExtra(getCanonicalExtra(exprExtra)));
1699
1672
  return reason;
1700
1673
  }
1701
1674
  function registerImportedFn({ node, ...importedFn }) {
@@ -1752,8 +1725,7 @@ function getStaticDeclRefs(path, refs = /* @__PURE__ */ new Set(), seen = /* @__
1752
1725
  const ids = decl.getOuterBindingIdentifiers();
1753
1726
  if (ids) for (const name in ids) {
1754
1727
  const binding = decl.scope.getBinding(name);
1755
- if (!binding) continue;
1756
- if (addBindingRefs(binding, refs, seen) === true) return true;
1728
+ if (binding) addBindingRefs(binding, refs, seen);
1757
1729
  }
1758
1730
  }
1759
1731
  return refs;
@@ -1764,34 +1736,15 @@ function addBindingRefs(binding, refs, seen) {
1764
1736
  const exprRoot = getExprRoot(ref);
1765
1737
  const markoRoot = getMarkoRoot(exprRoot);
1766
1738
  if (!markoRoot || canIgnoreRegister(markoRoot, exprRoot)) continue;
1767
- if (isStaticRoot(markoRoot)) {
1768
- if (getStaticDeclRefs(ref, refs, seen) === true) return true;
1769
- } else if (shouldAlwaysRegister(markoRoot)) return true;
1770
- else {
1771
- refs.add(exprRoot.node.extra ??= {});
1772
- if (getConstTagVarRefs(markoRoot, refs, seen) === true) return true;
1773
- }
1739
+ if (isStaticRoot(markoRoot)) getStaticDeclRefs(ref, refs, seen);
1740
+ else refs.add(exprRoot.node.extra ??= {});
1774
1741
  }
1775
1742
  }
1776
- function shouldAlwaysRegister(markoRoot) {
1777
- const tag = getTagFromMarkoRoot(markoRoot);
1778
- if (!tag) return false;
1779
- if (isCoreTagName(tag, "let")) return true;
1780
- if (isCoreTagName(tag, "return")) return true;
1781
- return analyzeTagNameType(tag) === 0;
1782
- }
1783
1743
  function hasSpreadAttributeAfter(attr) {
1784
1744
  const attrs = attr.parent.attributes;
1785
1745
  for (let i = attr.key + 1; i < attrs.length; i++) if (attrs[i].type === "MarkoSpreadAttribute") return true;
1786
1746
  return false;
1787
1747
  }
1788
- function getTagFromMarkoRoot(markoRoot) {
1789
- let cur = markoRoot;
1790
- do {
1791
- if (cur.isMarkoTag()) return cur;
1792
- cur = cur.parentPath;
1793
- } while (cur);
1794
- }
1795
1748
  function registerFunction(fnExtra, reason) {
1796
1749
  const { markoOpts, path: program, opts: { filename } } = (0, _marko_compiler_babel_utils.getFile)();
1797
1750
  program.node.extra.isInteractive = true;
@@ -1814,7 +1767,8 @@ function isStaticRoot(path) {
1814
1767
  //#region src/translator/util/analyze-errors.ts
1815
1768
  const [getHasAnalyzeErrors, setHasAnalyzeErrors] = createProgramState(() => false);
1816
1769
  function reportAnalyzeError(path, error) {
1817
- if (!(error instanceof Error)) throw error;
1770
+ const { filename } = error;
1771
+ if (!(error instanceof Error) || filename !== void 0 && filename !== path.hub.file.opts.filename) throw error;
1818
1772
  const { label = error.message, loc } = error;
1819
1773
  setHasAnalyzeErrors(true);
1820
1774
  (0, _marko_compiler_babel_utils.diagnosticError)(path, {
@@ -1837,20 +1791,15 @@ function isClientAssetImport(file, request) {
1837
1791
  //#endregion
1838
1792
  //#region src/translator/util/binding-has-prop.ts
1839
1793
  function isSectionRendererElided(section) {
1840
- return !!section.downstream?.binding && !bindingHasProperty(section.downstream.binding, section.downstream.properties);
1794
+ return !!section.downstream?.binding && !some(section.downstream.binding, (binding) => bindingHasProperty(binding, section.downstream.properties));
1841
1795
  }
1842
1796
  function bindingHasProperty(binding, properties) {
1843
1797
  if (binding.pruned) return false;
1844
1798
  else if (binding.pruned === void 0) throw new Error("Binding must be pruned before checking properties");
1845
1799
  if (binding.reads.size || !properties) return true;
1846
- let property;
1847
- let rest;
1848
- if (Array.isArray(properties)) {
1849
- property = properties[0];
1850
- rest = properties.length === 2 ? properties[1] : properties.slice(1);
1851
- } else property = properties;
1800
+ const property = first(properties);
1852
1801
  const propBinding = binding.propertyAliases.get(property);
1853
- if (propBinding && bindingHasProperty(propBinding, rest)) return true;
1802
+ if (propBinding && bindingHasProperty(propBinding, rest(properties))) return true;
1854
1803
  for (const alias of binding.aliases) if (bindingHasProperty(alias, properties)) return true;
1855
1804
  return false;
1856
1805
  }
@@ -1897,7 +1846,7 @@ function hasSupersetExcludeProperties(binding, excludeProperties) {
1897
1846
  return true;
1898
1847
  }
1899
1848
  function getKnownFromPropTree(propTree, name) {
1900
- return propTree === true ? true : propTree.props ? propTree.props[name] || (propTree.rest ? getKnownFromPropTree(propTree.rest, name) : void 0) : includes(propTree.binding.excludeProperties, name) ? void 0 : true;
1849
+ return propTree === true ? true : propTree.props ? propTree.props[name] || (propTree.rest ? getKnownFromPropTree(propTree.rest, name) : void 0) : propsUtil.has(propTree.binding.excludeProperties, name) ? void 0 : true;
1901
1850
  }
1902
1851
  function getAllKnownPropNames(propTree) {
1903
1852
  const keys = propTree.props ? Object.keys(propTree.props) : [];
@@ -1988,7 +1937,13 @@ function getStyleFile(file) {
1988
1937
  const fs = file.markoOpts.fileSystem;
1989
1938
  const base = getBase(filename);
1990
1939
  const styleMatch = new RegExp(`^(${escapeRegExp(base)}\\.${"index" === base ? "|" : ""})style\\.\\w+$`);
1991
- for (const file of fs.readdirSync(path.default.dirname(filename)).sort()) if (styleMatch.test(file)) return `./${file}`;
1940
+ let dirFiles;
1941
+ try {
1942
+ dirFiles = fs.readdirSync(path.default.dirname(filename)).sort();
1943
+ } catch {
1944
+ return;
1945
+ }
1946
+ for (const file of dirFiles) if (styleMatch.test(file)) return `./${file}`;
1992
1947
  }
1993
1948
  /**
1994
1949
  * Given a filename, gets the base name, strips off the file extension
@@ -2115,6 +2070,33 @@ function replaceUnsafeDoubleQuoteAttrChar(match) {
2115
2070
  return match === "\"" ? "&#34;" : match === "\r" ? "&#13;" : "&amp;";
2116
2071
  }
2117
2072
  //#endregion
2073
+ //#region src/translator/util/to-property-name.ts
2074
+ function getMemberExpressionPropString(expr) {
2075
+ switch (expr.property.type) {
2076
+ case "StringLiteral": return expr.property.value;
2077
+ case "NumericLiteral": return "" + expr.property.value;
2078
+ case "Identifier":
2079
+ if (expr.computed) return;
2080
+ return expr.property.name;
2081
+ }
2082
+ }
2083
+ function isValidPropertyIdentifier(name) {
2084
+ return /^[a-z_$][a-z0-9_$]*$/i.test(name);
2085
+ }
2086
+ function toPropertyName(name) {
2087
+ if (isValidPropertyIdentifier(name)) return _marko_compiler.types.identifier(name);
2088
+ else if (/^(?:0|[1-9][0-9]*)$/.test(name)) return _marko_compiler.types.numericLiteral(parseInt(name, 10));
2089
+ return _marko_compiler.types.stringLiteral(name);
2090
+ }
2091
+ function toObjectProperty(name, value) {
2092
+ return _marko_compiler.types.objectProperty(toPropertyName(name), value);
2093
+ }
2094
+ function toMemberExpression(object, key, optional) {
2095
+ const prop = toPropertyName(key);
2096
+ const computed = prop.type !== "Identifier";
2097
+ return optional ? _marko_compiler.types.optionalMemberExpression(object, prop, computed, true) : _marko_compiler.types.memberExpression(object, prop, computed);
2098
+ }
2099
+ //#endregion
2118
2100
  //#region src/translator/util/runtime.ts
2119
2101
  const pureDOMFunctions = /* @__PURE__ */ new Set([
2120
2102
  "_await_promise",
@@ -2163,11 +2145,25 @@ function importRuntime(name) {
2163
2145
  }
2164
2146
  return _marko_compiler.types.identifier(localName);
2165
2147
  }
2148
+ function registerRuntimeValue(id, value) {
2149
+ return _marko_compiler.types.assignmentExpression("=", toMemberExpression(importRuntime("_resumed"), id), value);
2150
+ }
2166
2151
  function callRuntime(name, ...args) {
2167
2152
  const callExpression = _marko_compiler.types.callExpression(importRuntime(name), filterArguments(args));
2168
2153
  if (isOutputDOM() && pureDOMFunctions.has(name)) return _marko_compiler.types.addComment(callExpression, "leading", "@__PURE__");
2169
2154
  return callExpression;
2170
2155
  }
2156
+ const domRuntimeFeatures = [
2157
+ "catch",
2158
+ "controllable",
2159
+ "controllable-input",
2160
+ "controllable-open",
2161
+ "controllable-select",
2162
+ "controllable-textarea",
2163
+ "dynamic-tag-script",
2164
+ "dynamic-tag-var",
2165
+ "placeholder"
2166
+ ];
2171
2167
  const importedFeatures = /* @__PURE__ */ new WeakMap();
2172
2168
  function importRuntimeFeature(feature) {
2173
2169
  if (!isTranslate()) throw new Error(`\`importRuntimeFeature(${JSON.stringify(feature)})\` may only be called during the translate stage.`);
@@ -2275,13 +2271,13 @@ function addExportRegistrations(node, seen, statements) {
2275
2271
  }
2276
2272
  }
2277
2273
  function buildRegistration(local, registerId) {
2278
- return _marko_compiler.types.expressionStatement(isOutputHTML() ? callRuntime("_resume", _marko_compiler.types.identifier(local), _marko_compiler.types.stringLiteral(registerId)) : callRuntime("_resume", _marko_compiler.types.stringLiteral(registerId), _marko_compiler.types.identifier(local)));
2274
+ return _marko_compiler.types.expressionStatement(isOutputHTML() ? callRuntime("_resume", _marko_compiler.types.identifier(local), _marko_compiler.types.stringLiteral(registerId)) : registerRuntimeValue(registerId, _marko_compiler.types.identifier(local)));
2279
2275
  }
2280
2276
  function resolveRegisterModule(file, { filename, exportName, registerId }) {
2281
2277
  const importer = file.opts.filename;
2282
2278
  return getMarkoOpts().resolveVirtualDependency(importer, {
2283
2279
  virtualPath: `${relativePath(importer, filename)}.register-${exportName}.js`,
2284
- code: `import { ${exportName} } from "./${path.default.basename(filename)}";\nimport { _resume } from "${getRuntimePath("dom")}";\n_resume(${JSON.stringify(registerId)}, ${exportName});\n`
2280
+ code: `import { ${exportName} } from "./${path.default.basename(filename)}";\nimport { _resumed } from "${getRuntimePath("dom")}";\n_resumed${isValidPropertyIdentifier(registerId) ? `.${registerId}` : `[${JSON.stringify(registerId)}]`} = ${exportName};\n`
2285
2281
  });
2286
2282
  }
2287
2283
  function relativePath(from, to) {
@@ -2425,28 +2421,55 @@ const [getSectionReasonState] = createSectionState("serializeReasonState", (sect
2425
2421
  guard: createTypeState(),
2426
2422
  declarators: [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(getSharedUid(`scope${section.id}_reason`, section)), callRuntime("_scope_reason"))]
2427
2423
  }));
2424
+ function buildGroupMask(groups) {
2425
+ let mask = 0;
2426
+ let maskNames = "";
2427
+ let dynamic;
2428
+ const props = [];
2429
+ let needsObject = false;
2430
+ let any = false;
2431
+ for (let i = 0; i < groups.length; i++) {
2432
+ const { value, names } = groups[i];
2433
+ if (value === void 0) continue;
2434
+ any = true;
2435
+ if (value === 0) continue;
2436
+ if (i >= 15) needsObject = true;
2437
+ else if (typeof value === "number") {
2438
+ mask |= value << 1 + 2 * i;
2439
+ if (names) maskNames += maskNames ? ` | ${names}` : names;
2440
+ } else {
2441
+ const shifted = _marko_compiler.types.binaryExpression("<<", value, withLeadingComment(_marko_compiler.types.numericLiteral(1 + 2 * i), names));
2442
+ dynamic = dynamic ? _marko_compiler.types.binaryExpression("|", dynamic, shifted) : shifted;
2443
+ }
2444
+ props.push(_marko_compiler.types.objectProperty(withLeadingComment(_marko_compiler.types.numericLiteral(i), names), typeof value === "number" ? _marko_compiler.types.numericLiteral(value) : value));
2445
+ }
2446
+ if (needsObject) return _marko_compiler.types.objectExpression(props);
2447
+ if (!any) return;
2448
+ const literal = mask ? withLeadingComment(_marko_compiler.types.numericLiteral(mask), maskNames) : void 0;
2449
+ return literal && dynamic ? _marko_compiler.types.binaryExpression("|", literal, dynamic) : literal || dynamic || _marko_compiler.types.numericLiteral(0);
2450
+ }
2428
2451
  function getScopeReasonDeclaration(section) {
2429
2452
  return _marko_compiler.types.variableDeclaration("const", getSectionReasonState(section).declarators);
2430
2453
  }
2431
2454
  function getSerializeGuard(section, reason, optional) {
2432
- if (!isReasonDynamic(reason) || isCrossSection(section, reason)) {
2455
+ if (!isDynamicSerializeGuard(section, reason)) {
2433
2456
  if (!reason) return _marko_compiler.types.numericLiteral(0);
2434
- return optional ? void 0 : withLeadingComment(_marko_compiler.types.numericLiteral(1), getDebugNames(reason === true ? void 0 : reason.state));
2457
+ return optional ? void 0 : withLeadingComment(_marko_compiler.types.numericLiteral(1), getDebugNames(reason.forced ? void 0 : reason.state));
2435
2458
  }
2436
2459
  return getOrHoist(reason, true);
2437
2460
  }
2438
2461
  function getSerializeGuardForAny(section, reasons, optional) {
2439
2462
  if (!Array.isArray(reasons)) return getSerializeGuard(section, reasons, optional);
2463
+ for (const reason of reasons) if (!isReasonDynamic(reason)) return optional ? void 0 : withLeadingComment(_marko_compiler.types.numericLiteral(1), getDebugNames(reason.state));
2440
2464
  let expr;
2441
2465
  for (const reason of reasons) {
2442
- if (!isReasonDynamic(reason)) return optional ? void 0 : withLeadingComment(_marko_compiler.types.numericLiteral(1), getDebugNames(reason.state));
2443
2466
  const guard = getSerializeGuard(section, reason, false);
2444
2467
  expr = expr ? _marko_compiler.types.logicalExpression("||", expr, guard) : guard;
2445
2468
  }
2446
2469
  return expr;
2447
2470
  }
2448
2471
  function getExprIfSerialized(section, reason, expr) {
2449
- if (!isReasonDynamic(reason) || isCrossSection(section, reason)) return reason && expr;
2472
+ if (!isDynamicSerializeGuard(section, reason)) return reason && expr;
2450
2473
  const guard = getOrHoist(reason, false);
2451
2474
  return guard ? _marko_compiler.types.logicalExpression("&&", guard, expr) : expr;
2452
2475
  }
@@ -2493,6 +2516,9 @@ function getOnlySection(params) {
2493
2516
  const { section } = params[0];
2494
2517
  return section === params[params.length - 1].section ? section : void 0;
2495
2518
  }
2519
+ function isDynamicSerializeGuard(section, reason) {
2520
+ return isReasonDynamic(reason) && !isCrossSection(section, reason);
2521
+ }
2496
2522
  function isCrossSection(section, reason) {
2497
2523
  return some(reason.param, (param) => !isSameOrChildSection(param.section, section));
2498
2524
  }
@@ -2586,7 +2612,7 @@ var return_default = {
2586
2612
  if (attrs.valueChange) {
2587
2613
  (attrs.valueChange.extra ??= {}).isEffect = true;
2588
2614
  addSetupExpr(section, attrs.valueChange);
2589
- addSerializeReason(section, true, getAccessorProp().TagVariableChange);
2615
+ addSerializeReason(section, FORCED, getAccessorProp().TagVariableChange);
2590
2616
  }
2591
2617
  addSetupExpr(section, attrs.value);
2592
2618
  section.returnValueExpr = attrs.value.extra ??= {};
@@ -2734,40 +2760,10 @@ function resolvesTo(read, canonical) {
2734
2760
  }
2735
2761
  function readsKey(read, keyBinding) {
2736
2762
  if (!read || read.getter) return false;
2737
- let binding = read.binding;
2738
- forEach(read.props, (prop) => {
2739
- binding = binding?.propertyAliases.get(prop);
2740
- });
2763
+ const binding = getPropertyAlias(read.binding, read.props);
2741
2764
  return !!binding && getCanonicalBinding(binding) === getCanonicalBinding(keyBinding);
2742
2765
  }
2743
2766
  //#endregion
2744
- //#region src/translator/util/to-property-name.ts
2745
- function getMemberExpressionPropString(expr) {
2746
- switch (expr.property.type) {
2747
- case "StringLiteral": return expr.property.value;
2748
- case "NumericLiteral": return "" + expr.property.value;
2749
- case "Identifier":
2750
- if (expr.computed) return;
2751
- return expr.property.name;
2752
- }
2753
- }
2754
- function isValidPropertyIdentifier(name) {
2755
- return /^[a-z_$][a-z0-9_$]*$/i.test(name);
2756
- }
2757
- function toPropertyName(name) {
2758
- if (isValidPropertyIdentifier(name)) return _marko_compiler.types.identifier(name);
2759
- else if (/^(?:0|[1-9][0-9]*)$/.test(name)) return _marko_compiler.types.numericLiteral(parseInt(name, 10));
2760
- return _marko_compiler.types.stringLiteral(name);
2761
- }
2762
- function toObjectProperty(name, value) {
2763
- return _marko_compiler.types.objectProperty(toPropertyName(name), value);
2764
- }
2765
- function toMemberExpression(object, key, optional) {
2766
- const prop = toPropertyName(key);
2767
- const computed = prop.type !== "Identifier";
2768
- return optional ? _marko_compiler.types.optionalMemberExpression(object, prop, computed, true) : _marko_compiler.types.memberExpression(object, prop, computed);
2769
- }
2770
- //#endregion
2771
2767
  //#region src/translator/util/get-declared-binding-expression.ts
2772
2768
  function getDeclaredBindingExpression(binding) {
2773
2769
  const canonicalBinding = getCanonicalBinding(binding);
@@ -2860,7 +2856,7 @@ function setSerializedValue(section, key, expression) {
2860
2856
  nonAnalyzedForceSerializedSection.add(section);
2861
2857
  getSerializedAccessors(section).set(key, {
2862
2858
  expression,
2863
- reason: true
2859
+ reason: FORCED
2864
2860
  });
2865
2861
  }
2866
2862
  const [getSectionWriteScopeBuilder, setSectionWriteScopeBuilder] = createSectionState("sectionWriteScopeBuilder");
@@ -2914,10 +2910,10 @@ function getSignal(section, referencedBindings, name) {
2914
2910
  if (isOutputHTML()) return signal;
2915
2911
  else if (!referencedBindings) signal.build = () => getSignalFn(signal);
2916
2912
  else if (Array.isArray(referencedBindings)) {
2917
- const collapseSource = collapsedIntersectionSource.get(referencedBindings);
2918
- subscribe(collapseSource || referencedBindings, signal);
2919
- if (collapseSource) {
2920
- const sourceSignal = getSignal(section, collapseSource);
2913
+ const meta = intersectionMeta.get(referencedBindings);
2914
+ subscribe(meta.source || referencedBindings, signal);
2915
+ if (meta.source) {
2916
+ const sourceSignal = getSignal(section, meta.source);
2921
2917
  forEach(referencedBindings, (member) => {
2922
2918
  const memberSignal = getSignal(section, member);
2923
2919
  const inline = member.type === 5 && !member.upstreamAlias && member.reads.size === 1 && sourceSignal.values.find((v) => v.signal === memberSignal);
@@ -2926,7 +2922,7 @@ function getSignal(section, referencedBindings, name) {
2926
2922
  });
2927
2923
  signal.build = () => getSignalFn(signal);
2928
2924
  } else signal.build = () => {
2929
- const { id, scopeOffset } = intersectionMeta.get(referencedBindings);
2925
+ const { id, scopeOffset } = meta;
2930
2926
  return callRuntime("_or", _marko_compiler.types.numericLiteral(id), getSignalFn(signal), scopeOffset || referencedBindings.length > 2 ? _marko_compiler.types.numericLiteral(referencedBindings.length - 1) : void 0, scopeOffset && getScopeAccessorLiteral(scopeOffset, true));
2931
2927
  };
2932
2928
  } else if (referencedBindings.section !== section && sectionUtil.has(referencedBindings.closureSections, section)) signal.build = () => {
@@ -2934,11 +2930,15 @@ function getSignal(section, referencedBindings, name) {
2934
2930
  const render = getSignalFn(signal);
2935
2931
  const closureSignalBuilder = getClosureSignalBuilder(section);
2936
2932
  if (closureSignalBuilder && !isDynamicClosure(section, closure)) return closureSignalBuilder(closure, render);
2937
- return callRuntime("_closure_get", isOptimize() ? _marko_compiler.types.numericLiteral(getClosureAccessorId(closure)) : getScopeAccessorLiteral(closure, true), render, isImmediateOwner(section, closure) ? void 0 : _marko_compiler.types.arrowFunctionExpression([scopeIdentifier], getScopeExpression(section, closure.section)), underTryPlaceholder(section) ? _marko_compiler.types.stringLiteral(getResumeRegisterId(section, closure, "pending")) : void 0);
2933
+ return callRuntime("_closure_get", isOptimize() ? _marko_compiler.types.numericLiteral(getClosureAccessorId(closure)) : getScopeAccessorLiteral(closure, true), render, isImmediateOwner(section, closure) ? void 0 : _marko_compiler.types.arrowFunctionExpression([scopeIdentifier], getScopeExpression(section, closure.section)), underTryPlaceholder(section) && closureResumes(closure) ? _marko_compiler.types.stringLiteral(getResumeRegisterId(section, closure, "pending")) : void 0);
2938
2934
  };
2939
2935
  }
2940
2936
  return signal;
2941
2937
  }
2938
+ function closureResumes(closure) {
2939
+ const state = closure.sources?.state;
2940
+ return !state || some(state, hasResumableWriter);
2941
+ }
2942
2942
  function underTryPlaceholder(section) {
2943
2943
  let curSection = section.parent;
2944
2944
  while (curSection) {
@@ -2954,8 +2954,7 @@ function initValue(binding, isLet = false) {
2954
2954
  signal.build = () => {
2955
2955
  if (isPureMemberForwarder(binding)) return;
2956
2956
  const fn = getSignalFn(signal);
2957
- const isDirectAlias = binding.upstreamAlias && binding.property === void 0 && binding.excludeProperties === void 0;
2958
- if (!signal.forcePersist && (isDirectAlias || !signal.hasSideEffect || !signalHasStatements(signal))) return fn;
2957
+ if (!signal.forcePersist && (isDirectAlias(binding) || !signal.hasSideEffect || !signalHasStatements(signal))) return fn;
2959
2958
  return callRuntime(isLet ? signal.extraArgs ? "_let_change" : "_let" : "_const", getScopeAccessorLiteral(binding, true, isLet), fn);
2960
2959
  };
2961
2960
  for (const alias of binding.aliases) if (alias.type !== 6) initValue(alias);
@@ -2971,7 +2970,7 @@ function signalHasStatements(signal) {
2971
2970
  return false;
2972
2971
  }
2973
2972
  function isPureMemberForwarder(binding) {
2974
- if (binding.property === void 0 || binding.reads.size || binding.exposed || binding.aliases.size || binding.assignmentSections || isForSelectorValue(binding) || getSerializeReason(binding.section, binding) || getSignal(binding.section, binding).hasSideEffect) return false;
2973
+ if (binding.property === void 0 || binding.reads.size || binding.exposed || binding.aliases.size || binding.assignments || isForSelectorValue(binding) || getSerializeReason(binding.section, binding) || getSignal(binding.section, binding).hasSideEffect) return false;
2975
2974
  for (const alias of binding.propertyAliases.values()) if (alias.type !== 6) return true;
2976
2975
  return false;
2977
2976
  }
@@ -3111,7 +3110,7 @@ function isOwnValueRead(node, binding) {
3111
3110
  function subscribe(references, subscriber) {
3112
3111
  if (references) forEach(references, (binding) => {
3113
3112
  if (binding.type !== 6) {
3114
- const source = binding.property === void 0 && binding.excludeProperties === void 0 && binding.upstreamAlias || binding;
3113
+ const source = isDirectAlias(binding) && binding.upstreamAlias || binding;
3115
3114
  const providerSignal = getSignal(subscriber.section, source);
3116
3115
  providerSignal.hasSideEffect = true;
3117
3116
  providerSignal.intersection = push(providerSignal.intersection, subscriber);
@@ -3162,8 +3161,7 @@ function addValue(targetSection, referencedBindings, signal, value) {
3162
3161
  function buildResumeRegisterKey(section, referencedBindings, type) {
3163
3162
  let name = "";
3164
3163
  if (referencedBindings) if (typeof referencedBindings === "string") name += `*${referencedBindings}`;
3165
- else if (Array.isArray(referencedBindings)) for (const ref of referencedBindings) name += `_${ref.name}#${ref.id}`;
3166
- else name += `_${referencedBindings.name}#${referencedBindings.id}`;
3164
+ else name = reduce(referencedBindings, appendBindingKey, name);
3167
3165
  return `${section.id}${name}${type ? "/" + type : ""}`;
3168
3166
  }
3169
3167
  function getResumeRegisterId(section, referencedBindings, type) {
@@ -3247,7 +3245,7 @@ function writeRegisteredFns() {
3247
3245
  else fn = _marko_compiler.types.functionDeclaration(_marko_compiler.types.identifier(registeredFn.id), registeredFn.node.params, registeredFn.node.body.type === "BlockStatement" ? registeredFn.node.body : _marko_compiler.types.blockStatement([_marko_compiler.types.returnStatement(registeredFn.node.body)]), registeredFn.node.generator, registeredFn.node.async);
3248
3246
  statements.push(fn);
3249
3247
  }
3250
- for (const registeredFn of registeredFns) statements.push(_marko_compiler.types.expressionStatement(callRuntime("_resume", _marko_compiler.types.stringLiteral(registeredFn.registerId), _marko_compiler.types.identifier(registeredFn.id))));
3248
+ for (const registeredFn of registeredFns) statements.push(_marko_compiler.types.expressionStatement(registerRuntimeValue(registeredFn.registerId, _marko_compiler.types.identifier(registeredFn.id))));
3251
3249
  (0, _marko_compiler_babel_utils.getProgram)().node.body.push(...statements);
3252
3250
  }
3253
3251
  }
@@ -3270,7 +3268,7 @@ function writeHTMLResumeStatements(path) {
3270
3268
  const allSignals = Array.from(getSignals(section).values());
3271
3269
  const scopeIdIdentifier = getScopeIdIdentifier(section);
3272
3270
  const markerSerializeArg = getSerializeGuardForAny(section, section.domSerializeReasons, true);
3273
- const sectionSerializeReason = nonAnalyzedForceSerializedSection.has(section) ? true : section.serializeReason;
3271
+ const sectionSerializeReason = nonAnalyzedForceSerializedSection.has(section) ? FORCED : section.serializeReason;
3274
3272
  forEach(section.referencedClosures, (closure) => {
3275
3273
  if (closure.sources) {
3276
3274
  if (isDynamicClosure(section, closure)) {
@@ -3284,7 +3282,7 @@ function writeHTMLResumeStatements(path) {
3284
3282
  const closureIndex = getDynamicClosureIndex(closure, section);
3285
3283
  if (closureIndex) setBindingSerializedValue(section, closure, _marko_compiler.types.numericLiteral(closureIndex), getAccessorPrefix().ClosureSignalIndex);
3286
3284
  const closureScopesReason = getSerializeReason(closure.section, closure, getAccessorPrefix().ClosureScopes);
3287
- if (underTryPlaceholder(section)) {
3285
+ if (underTryPlaceholder(section) && closureResumes(closure)) {
3288
3286
  const reason = getSerializeReason(section);
3289
3287
  if (reason) {
3290
3288
  const script = getExprIfSerialized(section, reason, callRuntime("_script", getScopeIdIdentifier(section), _marko_compiler.types.stringLiteral(getResumeRegisterId(section, closure, "pending")), markerSerializeArg));
@@ -3357,7 +3355,7 @@ function writeHTMLResumeStatements(path) {
3357
3355
  }
3358
3356
  body.push(_marko_compiler.types.expressionStatement(getExprIfSerialized(section, sectionSerializeReason, writeScopeBuilder ? writeScopeBuilder(callRuntime("_scope", ...writeScopeArgs)) : callRuntime("_scope", ...writeScopeArgs))));
3359
3357
  }
3360
- if (!section.isBranch && (section.hasAbortSignal || !!section.referencedClosures || sectionSerializeReason && !!find(section.bindings, (binding) => binding.type === 1)) && markerSerializeArg) {
3358
+ if (!section.isBranch && (section.hasAbortSignal || !!section.referencedClosures || sectionSerializeReason && some(section.bindings, isLetBinding)) && markerSerializeArg) {
3361
3359
  const call = callRuntime("_resume_branch", scopeIdIdentifier);
3362
3360
  const link = section.hasAbortSignal ? call : getExprIfSerialized(section, sectionSerializeReason, call);
3363
3361
  if (link) body.push(_marko_compiler.types.expressionStatement(markerSerializeArg.type === "NumericLiteral" ? link : _marko_compiler.types.logicalExpression("||", markerSerializeArg, link)));
@@ -3384,7 +3382,8 @@ function replaceBindingReadNode$1(node, signal) {
3384
3382
  case "Identifier":
3385
3383
  case "MemberExpression":
3386
3384
  case "OptionalMemberExpression": return getReadReplacement(node, signal);
3387
- case "CallExpression": {
3385
+ case "CallExpression":
3386
+ case "OptionalCallExpression": {
3388
3387
  const { extra } = node.callee;
3389
3388
  if (extra?.read) {
3390
3389
  const { binding, getter } = extra.read;
@@ -3542,6 +3541,12 @@ function getRegisteredFnExpression$1(node) {
3542
3541
  else return _marko_compiler.types.identifier(id);
3543
3542
  }
3544
3543
  }
3544
+ function appendBindingKey(name, binding) {
3545
+ return `${name}_${binding.name}#${binding.id}`;
3546
+ }
3547
+ function isLetBinding(binding) {
3548
+ return binding.type === 1;
3549
+ }
3545
3550
  //#endregion
3546
3551
  //#region src/translator/util/import-reference.ts
3547
3552
  function importOrSelfReferenceName(file, request, name, nameHint) {
@@ -3941,7 +3946,8 @@ function replaceBindingReadNode(node) {
3941
3946
  if (extra && !(extra.read && !extra.read.binding.declared || extra.binding && !extra.binding.declared)) return getReadReplacement(node);
3942
3947
  break;
3943
3948
  }
3944
- case "CallExpression": {
3949
+ case "CallExpression":
3950
+ case "OptionalCallExpression": {
3945
3951
  const read = node.callee.extra?.read;
3946
3952
  if (read && (read.getter !== void 0 || read.binding.type === 0)) return _marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.cloneNode(node.callee)], node), [importRuntime(read.binding.type === 0 ? "_el_read_error" : "_hoist_read_error")]);
3947
3953
  break;
@@ -4125,6 +4131,8 @@ var for_default = {
4125
4131
  const keyAttr = tag.node.attributes.find((attr) => attr.type === "MarkoAttribute" && attr.name === "key");
4126
4132
  if (keyAttr) throw tag.hub.buildError(keyAttr, `The [\`<for>\` tag](https://markojs.com/docs/reference/core-tag#for) keys items with the \`by=\` attribute, not \`key=\`. ${forType === "of" ? "Use `by=\"propName\"` or `by=(item, index) => key`" : forType === "in" ? "Use `by=(key, value) => key`" : "Use `by=(num) => key`"}.`);
4127
4133
  (0, _marko_compiler_babel_utils.assertAllowedAttributes)(tag, allowAttrs);
4134
+ const extraParam = tag.node.body.params[forType === "of" || forType === "in" ? 2 : 1];
4135
+ if (extraParam && extraParam.type !== "RestElement") throw tag.hub.buildError(extraParam, `The [\`<for>\` tag](https://markojs.com/docs/reference/core-tag#for) only provides \`|${forType === "of" ? "item, index" : forType === "in" ? "key, value" : "num"}|\` with \`${forType}=\`, so this parameter is never supplied.`);
4128
4136
  if (isAttrTag) return;
4129
4137
  const byAttr = getKnownAttrValues(tag.node).by;
4130
4138
  if (forType !== "of" && byAttr?.type === "StringLiteral") throw tag.hub.buildError(byAttr, `The [\`<for>\` tag](https://markojs.com/docs/reference/core-tag#for) only supports a string \`by\` key with \`of\`; use a \`by=(${forType === "in" ? "key, value" : "index"}) => ...\` function for \`<for ${forType}>\`.`);
@@ -4535,8 +4543,9 @@ function translateAttrs(tag, propTree = true, skip, statements = [], contentKey
4535
4543
  for (let i = attributes.length; i--;) {
4536
4544
  const attr = attributes[i];
4537
4545
  const { value } = attr;
4538
- if (_marko_compiler.types.isMarkoSpreadAttribute(attr)) attrProperties.push(_marko_compiler.types.spreadElement(value));
4539
- else if (!seen.has(attr.name) && getKnownFromPropTree(propTree, attr.name)) {
4546
+ if (_marko_compiler.types.isMarkoSpreadAttribute(attr)) {
4547
+ if (!value.extra?.pruned) attrProperties.push(_marko_compiler.types.spreadElement(value));
4548
+ } else if (!seen.has(attr.name) && getKnownFromPropTree(propTree, attr.name)) {
4540
4549
  seen.add(attr.name);
4541
4550
  attrProperties.push(toObjectProperty(attr.name, value));
4542
4551
  }
@@ -4706,10 +4715,12 @@ var native_tag_default = {
4706
4715
  hasEventHandlers = true;
4707
4716
  } else {
4708
4717
  assertValidNativeEventHandlerAttr(tag, attr);
4718
+ if (isEventOrChangeHandler(attr.name)) valueExtra.forceRegister = true;
4709
4719
  if (!evaluate(attr.value).confident) hasDynamicAttributes = true;
4710
4720
  }
4711
4721
  } else if (_marko_compiler.types.isMarkoSpreadAttribute(attr)) {
4712
4722
  valueExtra.isEffect = true;
4723
+ valueExtra.forceRegister = true;
4713
4724
  hasEventHandlers = true;
4714
4725
  hasDynamicAttributes = true;
4715
4726
  }
@@ -4761,9 +4772,7 @@ var native_tag_default = {
4761
4772
  const spreadBinding = node.extra?.spreadFrom;
4762
4773
  if (spreadBinding) {
4763
4774
  spreadBinding.noSerialize = true;
4764
- if (carveProperties) {
4765
- for (const property of carveProperties) if (!includes(spreadBinding.noSerializeProperties, property)) spreadBinding.noSerializeProperties = push(spreadBinding.noSerializeProperties, property);
4766
- }
4775
+ if (carveProperties) for (const property of carveProperties) spreadBinding.noSerializeProperties = propsUtil.add(spreadBinding.noSerializeProperties, property);
4767
4776
  }
4768
4777
  }
4769
4778
  }
@@ -4778,7 +4787,7 @@ var native_tag_default = {
4778
4787
  const attr = seen[name];
4779
4788
  if (isEventHandler(name) || name === "content" || !evaluate(attr.value).confident) addSetupExpr(tagSection, attr.value);
4780
4789
  }
4781
- addSerializeExpr(tagSection, !!(node.var || hasEventHandlers), nodeBinding);
4790
+ if (node.var || hasEventHandlers) addSerializeReason(tagSection, FORCED, nodeBinding);
4782
4791
  trackDomVarReferences(tag, nodeBinding);
4783
4792
  addSerializeExpr(tagSection, push(exprExtras, tagExtra), nodeBinding);
4784
4793
  }
@@ -5580,7 +5589,7 @@ const IfTag = {
5580
5589
  if (branchBodySection) {
5581
5590
  const branchSerializeReason = getSerializeReason(branchBodySection, kBranchSerializeReason);
5582
5591
  if (branchSerializeReason) {
5583
- if (branchSerializeReasons !== true) branchSerializeReasons = branchSerializeReason === true || branchSerializeReason.state ? true : sourcesUtil.add(branchSerializeReasons, branchSerializeReason);
5592
+ branchSerializeReasons = sourcesUtil.add(branchSerializeReasons, branchSerializeReason);
5584
5593
  bodyStatements.push(_marko_compiler.types.returnStatement(_marko_compiler.types.numericLiteral(i)));
5585
5594
  }
5586
5595
  }
@@ -6145,6 +6154,48 @@ var program_default = {
6145
6154
  }
6146
6155
  };
6147
6156
  //#endregion
6157
+ //#region src/translator/util/cyclic-memo.ts
6158
+ function createCyclicMemo(compute, cycleAnswer) {
6159
+ const cache = /* @__PURE__ */ new WeakMap();
6160
+ const computing = /* @__PURE__ */ new Map();
6161
+ let provisionalAt = Infinity;
6162
+ return (key) => {
6163
+ if (cache.has(key)) return cache.get(key);
6164
+ const at = computing.get(key);
6165
+ if (at !== void 0) {
6166
+ if (at < provisionalAt) provisionalAt = at;
6167
+ return cycleAnswer;
6168
+ }
6169
+ const frame = computing.size;
6170
+ computing.set(key, frame);
6171
+ const outerProvisionalAt = provisionalAt;
6172
+ provisionalAt = Infinity;
6173
+ try {
6174
+ const result = compute(key);
6175
+ if (provisionalAt >= frame) cache.set(key, result);
6176
+ return result;
6177
+ } finally {
6178
+ computing.delete(key);
6179
+ if (provisionalAt >= frame || outerProvisionalAt < provisionalAt) provisionalAt = outerProvisionalAt;
6180
+ }
6181
+ };
6182
+ }
6183
+ function createCyclicPathMemo(compute, cycleAnswer) {
6184
+ const keys = /* @__PURE__ */ new WeakMap();
6185
+ const memo = createCyclicMemo(([key, path]) => compute(key, path), cycleAnswer);
6186
+ return (key, path) => {
6187
+ let node = keys.get(key);
6188
+ if (!node) keys.set(key, node = {});
6189
+ if (path === true) return memo(node.all ??= [key, path]);
6190
+ forEach(path, (property) => {
6191
+ let next = node.props?.get(property);
6192
+ if (!next) (node.props ??= /* @__PURE__ */ new Map()).set(property, next = {});
6193
+ node = next;
6194
+ });
6195
+ return memo(node.value ??= [key, path]);
6196
+ };
6197
+ }
6198
+ //#endregion
6148
6199
  //#region src/translator/util/set-tag-sections-downstream.ts
6149
6200
  const [getTagDownstreams] = createSectionState("tag-downstreams", () => /* @__PURE__ */ new Map());
6150
6201
  function setTagDownstream(tag, binding, exprs) {
@@ -6160,14 +6211,13 @@ function crawlSectionsAndSetBinding(tag, downstreamTag, binding, exprs, properti
6160
6211
  if (!skip) {
6161
6212
  const contentSection = getSectionForBody(tag.get("body"));
6162
6213
  if (contentSection) {
6163
- let target = binding;
6164
- forEach(properties, (property) => {
6165
- target = target?.propertyAliases.get(property);
6214
+ const serialized = filter(binding, (binding) => {
6215
+ const target = getPropertyAlias(binding, properties);
6216
+ return !(target && (target.noSerialize || propsUtil.has(target.noSerializeProperties, "content")));
6166
6217
  });
6167
- const serialized = !(target && (target.noSerialize || includes(target.noSerializeProperties, "content")));
6168
6218
  contentSection.downstream = {
6169
6219
  tag: downstreamTag,
6170
- binding: serialized ? binding : void 0,
6220
+ binding: serialized,
6171
6221
  properties: serialized ? concat(properties, "content") : void 0,
6172
6222
  exprs: serialized ? exprs : void 0
6173
6223
  };
@@ -6193,7 +6243,7 @@ function translateVar(tag, initialValue, kind = "const", statements) {
6193
6243
  if (!idExtra) return;
6194
6244
  const binding = idExtra.binding;
6195
6245
  if (!binding?.upstreamAlias) return;
6196
- if (binding.assignmentSections && binding.property !== void 0) {
6246
+ if (binding.assignments && binding.property !== void 0) {
6197
6247
  const changeName = binding.property + "Change";
6198
6248
  const changeBinding = binding.upstreamAlias.propertyAliases.get(changeName);
6199
6249
  if (changeBinding && changeName !== changeBinding.name) {
@@ -6253,14 +6303,24 @@ function knownTagAnalyze(tag, contentSection, propTree) {
6253
6303
  if (varBinding) {
6254
6304
  addSetupStatement(section);
6255
6305
  const mutatesTagVar = !!(tag.node.var.type === "Identifier" && tag.scope.getBinding(tag.node.var.name)?.constantViolations.length);
6256
- const varExpr = tagExtra.defineBodySection ? contentSection.returnValueExpr : mapParamReasonToExpr(exprs, contentSection.returnSerializeReason && (contentSection.returnSerializeReason === true || !!contentSection.returnSerializeReason.state || contentSection.returnSerializeReason.param));
6306
+ const varExpr = tagExtra.defineBodySection ? contentSection.returnValueExpr : mapParamReasonToExpr(exprs, contentSection.returnSerializeReason && (contentSection.returnSerializeReason.forced || !!contentSection.returnSerializeReason.state || contentSection.returnSerializeReason.param));
6257
6307
  varBinding.scopeOffset = tagExtra[kChildOffsetScopeBinding$1] = createBinding("#scopeOffset", 0, section);
6258
6308
  setBindingDownstream(varBinding, varExpr);
6259
- if (mutatesTagVar) addSerializeExpr(section, true, childScopeBinding);
6260
- addSerializeExpr(section, varExpr, childScopeBinding);
6309
+ if (mutatesTagVar || varExpr === true) addSerializeReason(section, FORCED, childScopeBinding);
6310
+ if (varExpr !== true) addSerializeExpr(section, varExpr, childScopeBinding);
6261
6311
  }
6262
6312
  addSerializeExpr(section, fromIter(attrExprs), childScopeBinding);
6263
6313
  }
6314
+ function getRenderArgs(tag) {
6315
+ const args = tag.node.arguments;
6316
+ return args?.length && !args.every(isPrunedNode) ? args.map(toRenderArg) : null;
6317
+ }
6318
+ function isPrunedNode(node) {
6319
+ return !!node.extra?.pruned;
6320
+ }
6321
+ function toRenderArg(arg) {
6322
+ return isPrunedNode(arg) ? _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0)) : arg;
6323
+ }
6264
6324
  function knownTagTranslateHTML(tag, tagIdentifier, contentSection, propTree) {
6265
6325
  const tagBody = tag.get("body");
6266
6326
  const { node } = tag;
@@ -6284,39 +6344,20 @@ function knownTagTranslateHTML(tag, tagIdentifier, contentSection, propTree) {
6284
6344
  if (tagVar) varStatement = _marko_compiler.types.expressionStatement(callRuntime("_var", getScopeIdIdentifier(section), getScopeAccessorLiteral(tag.node.extra[kChildOffsetScopeBinding$1]), peekScopeId, _marko_compiler.types.stringLiteral(getResumeRegisterId(section, tagVar.extra?.binding, "var"))));
6285
6345
  }
6286
6346
  if (contentSection.paramReasonGroups) {
6287
- let childSerializeReasonExpr;
6288
- if (contentSection.paramReasonGroups.length === 1) {
6289
- const [group] = contentSection.paramReasonGroups;
6347
+ const childSerializeReasonExpr = buildGroupMask(contentSection.paramReasonGroups.map((group) => {
6290
6348
  const reason = getSerializeReason(section, childScopeBinding, group.id);
6291
- childSerializeReasonExpr = reason && getSerializeGuard(section, reason, false);
6292
- } else {
6293
- const props = [];
6294
- let bitmask = 0;
6295
- let bitmaskNames = "";
6296
- let hasDynamicReasons = false;
6297
- let hasSkippedReasons = false;
6298
- for (let i = 0; i < contentSection.paramReasonGroups.length; i++) {
6299
- const group = contentSection.paramReasonGroups[i];
6300
- const reason = getSerializeReason(section, childScopeBinding, group.id);
6301
- if (reason) {
6302
- hasDynamicReasons ||= reason !== true && !reason.state;
6303
- const guard = getSerializeGuard(section, reason, false);
6304
- if (bitmask >= 0) if (guard.type === "NumericLiteral" && guard.value === 1 && i < 30) {
6305
- bitmask |= 1 << i + 1;
6306
- const names = getDebugNames(group.reason);
6307
- if (names) bitmaskNames += bitmaskNames ? ` | ${names}` : names;
6308
- } else bitmask = -1;
6309
- props.push(_marko_compiler.types.objectProperty(withLeadingComment(_marko_compiler.types.numericLiteral(i), getDebugNames(group.reason)), guard));
6310
- } else hasSkippedReasons = true;
6311
- }
6312
- if (props.length) childSerializeReasonExpr = !(hasDynamicReasons || hasSkippedReasons) ? _marko_compiler.types.numericLiteral(1) : bitmask > 0 ? withLeadingComment(_marko_compiler.types.numericLiteral(bitmask), bitmaskNames) : _marko_compiler.types.objectExpression(props);
6313
- }
6349
+ const guard = reason && getSerializeGuard(section, reason, false);
6350
+ return {
6351
+ value: !guard ? void 0 : guard.type === "NumericLiteral" ? guard.value : guard,
6352
+ names: getDebugNames(group.reason)
6353
+ };
6354
+ }));
6314
6355
  if (childSerializeReasonExpr) tag.insertBefore(_marko_compiler.types.expressionStatement(callRuntime("_set_serialize_reason", childSerializeReasonExpr)));
6315
6356
  }
6316
6357
  const getArgs = () => {
6317
- let renderArgs = [];
6318
- if (tag.node.arguments) renderArgs = [...renderArgs, ...tag.node.arguments];
6319
- if (!tag.node.arguments?.length || properties.length) renderArgs.push(propsToExpression(properties));
6358
+ const args = getRenderArgs(tag);
6359
+ const renderArgs = args ? [...args] : [];
6360
+ if (!args || properties.length) renderArgs.push(propsToExpression(properties));
6320
6361
  return renderArgs;
6321
6362
  };
6322
6363
  if (tagVar) {
@@ -6506,12 +6547,12 @@ function analyzeAttrs(rootTagExtra, section, tag, propTree, rootAttrExprs, rootE
6506
6547
  addSetupExpr(section, attr.value);
6507
6548
  setBindingDownstream(templateExportAttr.binding, attrExtra, rootExprs);
6508
6549
  if (getRootSection(templateExportAttr.binding.section) !== (0, _marko_compiler_babel_utils.getProgram)().node.extra.section && isInvokeOnlyBinding(templateExportAttr.binding)) attrExtra.invokeOnly = true;
6509
- if (knownSpread && !includes(knownSpread.binding.excludeProperties, attr.name)) addRead(attrExtra, {}, getOrCreatePropertyAlias(knownSpread.binding, attr.name), section, void 0);
6550
+ if (knownSpread && !propsUtil.has(knownSpread.binding.excludeProperties, attr.name)) addRead(attrExtra, {}, getOrCreatePropertyAlias(knownSpread.binding, attr.name), section, void 0);
6510
6551
  }
6511
6552
  } else if (spreadReferenceNodes) spreadReferenceNodes.push(attr.value);
6512
6553
  else {
6513
6554
  knownSpread = hasAllKnownProps(propTree) ? getSingleKnownSpread(attributes) : void 0;
6514
- if (knownSpread) dropNodes(attr.value);
6555
+ if (knownSpread) untrackNode(attr.value);
6515
6556
  else (spreadReferenceNodes = restReferenceNodes || []).push(attr.value);
6516
6557
  }
6517
6558
  }
@@ -6544,7 +6585,7 @@ function getSingleKnownSpread(attributes) {
6544
6585
  let extra;
6545
6586
  for (let i = attributes.length; i--;) {
6546
6587
  const attr = attributes[i];
6547
- if (attr.type === "MarkoSpreadAttribute" ? binding || !(binding = (extra = attr.value.extra)?.spreadFrom) : binding && !includes(binding.excludeProperties, attr.name)) return;
6588
+ if (attr.type === "MarkoSpreadAttribute" ? binding || !(binding = (extra = attr.value.extra)?.spreadFrom) : binding && !propsUtil.has(binding.excludeProperties, attr.name)) return;
6548
6589
  }
6549
6590
  if (binding) return {
6550
6591
  extra,
@@ -6557,8 +6598,9 @@ function writeParamsToSignals(tag, propTree, importAlias, info) {
6557
6598
  const tagInputIdentifier = info.getBindingIdentifier(propTree.binding, `${importAlias}_params`);
6558
6599
  const translatedAttrs = translateAttrs(tag);
6559
6600
  if (translatedAttrs.statements.length) addStatement("render", info.tagSection, referencedBindings, translatedAttrs.statements);
6560
- const renderParams = tag.node.arguments ? [...tag.node.arguments] : [];
6561
- if (!tag.node.arguments?.length || translatedAttrs.properties.length) renderParams.push(propsToExpression(translatedAttrs.properties));
6601
+ const args = getRenderArgs(tag);
6602
+ const renderParams = args ? [...args] : [];
6603
+ if (!args || translatedAttrs.properties.length) renderParams.push(propsToExpression(translatedAttrs.properties));
6562
6604
  addStatement("render", info.tagSection, referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(tagInputIdentifier, [createScopeReadExpression(info.childScopeBinding, info.tagSection), _marko_compiler.types.arrayExpression(renderParams)])));
6563
6605
  return;
6564
6606
  }
@@ -6786,10 +6828,17 @@ function getRootSection(section) {
6786
6828
  //#endregion
6787
6829
  //#region src/translator/util/references.ts
6788
6830
  const kBranchSerializeReason = Symbol("branch serialize reason");
6831
+ const FORCED = {
6832
+ state: void 0,
6833
+ param: void 0,
6834
+ global: void 0,
6835
+ forced: true
6836
+ };
6789
6837
  const globalSources = {
6790
6838
  state: void 0,
6791
6839
  param: void 0,
6792
- global: true
6840
+ global: true,
6841
+ forced: void 0
6793
6842
  };
6794
6843
  const [getBindings] = createProgramState(() => /* @__PURE__ */ new Set());
6795
6844
  const [getNextBindingId, setNextBindingId] = createProgramState(() => 0);
@@ -6809,11 +6858,12 @@ function createBinding(name, type, refSection, upstreamAlias, property, excludeP
6809
6858
  property,
6810
6859
  declared,
6811
6860
  closureSections: void 0,
6812
- assignmentSections: void 0,
6861
+ assignments: void 0,
6813
6862
  excludeProperties,
6814
6863
  noSerialize: false,
6815
6864
  noSerializeProperties: void 0,
6816
6865
  sources: void 0,
6866
+ upstreamIntersection: void 0,
6817
6867
  reads: /* @__PURE__ */ new Set(),
6818
6868
  aliases: /* @__PURE__ */ new Set(),
6819
6869
  hoists: void 0,
@@ -6846,8 +6896,18 @@ function createBinding(name, type, refSection, upstreamAlias, property, excludeP
6846
6896
  return binding;
6847
6897
  }
6848
6898
  function getOrCreatePropertyAlias(binding, property) {
6899
+ while (isDirectAlias(binding)) binding = binding.upstreamAlias;
6849
6900
  return binding.propertyAliases.get(property) || createBinding(`${binding.name}_${property.replace(/[^a-zA-Z0-9_$]/g, "_")}`, binding.type, binding.section, binding, property);
6850
6901
  }
6902
+ function getPropertyAlias(binding, properties) {
6903
+ return reduce(properties, getExistingPropertyAlias, binding);
6904
+ }
6905
+ function getExistingPropertyAlias(binding, property) {
6906
+ while (binding) {
6907
+ if (!isDirectAlias(binding)) return binding.propertyAliases.get(property);
6908
+ binding = binding.upstreamAlias;
6909
+ }
6910
+ }
6851
6911
  function trackDomVarReferences(tag, binding) {
6852
6912
  const tagVar = tag.node.var;
6853
6913
  if (!tagVar) return;
@@ -6866,7 +6926,7 @@ function trackDomVarReferences(tag, binding) {
6866
6926
  } : void 0);
6867
6927
  if (refSection !== binding.section) {
6868
6928
  setReadsOwner(refSection, section);
6869
- addOwnerSerializeReason(refSection, section, true);
6929
+ addOwnerSerializeReason(refSection, section, FORCED);
6870
6930
  }
6871
6931
  }
6872
6932
  return binding;
@@ -6985,10 +7045,12 @@ function trackAssignment(assignment, binding) {
6985
7045
  const idExtra = id.node.extra ??= {};
6986
7046
  idExtra.assignment = binding;
6987
7047
  idExtra.section = section;
6988
- binding.assignmentSections = sectionUtil.add(binding.assignmentSections, section);
7048
+ idExtra.exprRoot = getExprRoot(fnRoot || assignment).node.extra ??= {};
7049
+ idExtra.fnRoot = fnExtra;
7050
+ getAssignments().push(idExtra);
6989
7051
  if (fnExtra) {
6990
- idExtra.assignmentFunction = fnExtra;
6991
- fnExtra.section = idExtra.section = section;
7052
+ fnExtra.section = section;
7053
+ fnExtra.exprRoot = idExtra.exprRoot;
6992
7054
  }
6993
7055
  if (binding.upstreamAlias && binding.property !== void 0) {
6994
7056
  if (binding.upstreamAlias === binding.section.params) throw assignment.buildCodeFrameError(`\`${binding.name}\` is a tag parameter and cannot be assigned to.`);
@@ -7027,10 +7089,7 @@ function createBindingsAndTrackReferences(lVal, type, scope, section, upstreamAl
7027
7089
  else if (prop.key.type === "StringLiteral") key = prop.key.value;
7028
7090
  else throw scope.path.hub.buildError(prop.key, "Only identifier and string literal keys are supported when destructuring.");
7029
7091
  if (hasRest) excludeProperties = propsUtil.add(excludeProperties, key);
7030
- if (_marko_compiler.types.isLVal(prop.value)) {
7031
- createBindingsAndTrackReferences(prop.value, type, scope, section, patternBinding, key, void 0);
7032
- if (hasRest && prop.value.extra?.binding?.assignmentSections) excludeProperties = propsUtil.add(excludeProperties, `${key}Change`);
7033
- }
7092
+ if (_marko_compiler.types.isLVal(prop.value)) createBindingsAndTrackReferences(prop.value, type, scope, section, patternBinding, key, void 0);
7034
7093
  }
7035
7094
  break;
7036
7095
  }
@@ -7055,7 +7114,7 @@ function trackReference(referencePath, binding) {
7055
7114
  let reference = binding;
7056
7115
  while (true) {
7057
7116
  const { parent } = root;
7058
- if (!_marko_compiler.types.isMemberExpression(parent) && !_marko_compiler.types.isOptionalMemberExpression(parent)) break;
7117
+ if (!_marko_compiler.types.isMemberExpression(parent) && !_marko_compiler.types.isOptionalMemberExpression(parent) || isWrittenMember(root.parentPath)) break;
7059
7118
  let prop = getMemberExpressionPropString(parent);
7060
7119
  if (prop === void 0) break;
7061
7120
  if (reference.upstreamAlias && reference.excludeProperties !== void 0) {
@@ -7072,23 +7131,38 @@ function trackReference(referencePath, binding) {
7072
7131
  }
7073
7132
  addReadToExpression(root, reference, void 0);
7074
7133
  }
7134
+ function isWrittenMember(member) {
7135
+ const { node, parent } = member;
7136
+ switch (parent.type) {
7137
+ case "AssignmentExpression":
7138
+ case "AssignmentPattern":
7139
+ case "ForInStatement":
7140
+ case "ForOfStatement": return parent.left === node;
7141
+ case "UnaryExpression": return parent.operator === "delete";
7142
+ case "UpdateExpression":
7143
+ case "ArrayPattern":
7144
+ case "RestElement": return true;
7145
+ case "ObjectProperty": return parent.value === node && _marko_compiler.types.isObjectPattern(member.parentPath.parent);
7146
+ default: return false;
7147
+ }
7148
+ }
7075
7149
  function mergeReferences(section, target, nodes) {
7076
7150
  const targetExtra = target.extra ??= {};
7077
7151
  const readsByExpression = getReadsByExpression();
7078
7152
  const fnReadsByExpression = getFunctionReadsByExpression();
7079
7153
  let reads = readsByExpression.get(targetExtra);
7080
7154
  let exprFnReads = fnReadsByExpression.get(targetExtra);
7081
- let { isEffect, dynamicTagInput } = targetExtra;
7155
+ let { isEffect, forceRegister } = targetExtra;
7082
7156
  for (const node of nodes) {
7083
7157
  if (!node) continue;
7084
7158
  const extra = node.extra ??= {};
7085
7159
  if (extra === targetExtra) continue;
7086
7160
  extra.merged = targetExtra;
7161
+ forceRegister ||= extra.forceRegister;
7087
7162
  if (isReferencedExtra(extra)) {
7088
7163
  const additionalReads = readsByExpression.get(extra);
7089
7164
  const additionalExprFnReads = fnReadsByExpression.get(extra);
7090
7165
  isEffect ||= extra.isEffect;
7091
- dynamicTagInput ||= extra.dynamicTagInput;
7092
7166
  if (additionalReads) {
7093
7167
  forEach(additionalReads, (read) => {
7094
7168
  read.binding.reads.delete(extra);
@@ -7105,7 +7179,7 @@ function mergeReferences(section, target, nodes) {
7105
7179
  }
7106
7180
  readsByExpression.set(targetExtra, reads);
7107
7181
  targetExtra.isEffect = isEffect;
7108
- targetExtra.dynamicTagInput = dynamicTagInput;
7182
+ targetExtra.forceRegister = forceRegister;
7109
7183
  targetExtra.section = section;
7110
7184
  return targetExtra;
7111
7185
  }
@@ -7131,6 +7205,33 @@ function finalizeReferences() {
7131
7205
  const readsByExpression = getReadsByExpression();
7132
7206
  const fnReadsByExpression = getFunctionReadsByExpression();
7133
7207
  const intersectionsBySection = /* @__PURE__ */ new Map();
7208
+ const assignments = getAssignments();
7209
+ for (const idExtra of assignments) if (inEmittedExpr(idExtra)) {
7210
+ const binding = idExtra.assignment;
7211
+ binding.assignments = push(binding.assignments, idExtra);
7212
+ }
7213
+ for (const binding of bindings) {
7214
+ if (binding.type !== 0) {
7215
+ if (pruneBinding(binding, true)) bindings.delete(binding);
7216
+ }
7217
+ if (binding.noSerialize) if (isPureSpreadResolved(binding)) if (hasAnyMemberAccess(binding)) {
7218
+ binding.noSerialize = false;
7219
+ binding.noSerializeProperties = propsUtil.filter(binding.noSerializeProperties, (property) => !isPropertyMemberAccessed(binding, property));
7220
+ } else binding.noSerializeProperties = void 0;
7221
+ else {
7222
+ binding.noSerialize = false;
7223
+ binding.noSerializeProperties = void 0;
7224
+ }
7225
+ }
7226
+ const excluded = /* @__PURE__ */ new Set();
7227
+ for (const idExtra of assignments) {
7228
+ const binding = idExtra.assignment;
7229
+ if (!inEmittedExpr(idExtra)) binding.assignments = filter(binding.assignments, inEmittedExpr);
7230
+ else if (!excluded.has(binding) && binding.upstreamAlias && binding.property !== void 0) {
7231
+ excluded.add(binding);
7232
+ for (const alias of binding.upstreamAlias.aliases) if (propsUtil.has(alias.excludeProperties, binding.property)) alias.excludeProperties = propsUtil.add(alias.excludeProperties, binding.property + "Change");
7233
+ }
7234
+ }
7134
7235
  for (const [expr, reads] of readsByExpression) if (isReferencedExtra(expr)) {
7135
7236
  const exprBindings = resolveReferencedBindings(expr, reads, intersectionsBySection);
7136
7237
  expr.referencedBindings = exprBindings.referencedBindings;
@@ -7143,13 +7244,13 @@ function finalizeReferences() {
7143
7244
  if (exprBindings.hoistedBindings) expr.section.referencedHoists = bindingUtil.union(expr.section.referencedHoists, exprBindings.hoistedBindings);
7144
7245
  if (expr.isEffect) {
7145
7246
  forEach(exprBindings.referencedBindings, (binding) => {
7146
- addSerializeReason(binding.section, true, binding);
7247
+ addSerializeReason(binding.section, FORCED, binding);
7147
7248
  });
7148
7249
  forEach(exprBindings.constantBindings, (binding) => {
7149
- addSerializeReason(binding.section, true, binding);
7250
+ addSerializeReason(binding.section, FORCED, binding);
7150
7251
  });
7151
7252
  forEach(exprBindings.lazyBindings, (binding) => {
7152
- addSerializeReason(binding.section, true, binding);
7253
+ addSerializeReason(binding.section, FORCED, binding);
7153
7254
  });
7154
7255
  } else forEach(reads, (read) => {
7155
7256
  if (read.serializedValue) addSerializeExpr(read.binding.section, expr, read.binding);
@@ -7164,23 +7265,6 @@ function finalizeReferences() {
7164
7265
  }
7165
7266
  }
7166
7267
  const bindingNamesBySection = /* @__PURE__ */ new Map();
7167
- for (const binding of bindings) {
7168
- if (binding.type !== 0) {
7169
- if (pruneBinding(binding)) bindings.delete(binding);
7170
- }
7171
- if (binding.noSerialize) if (isPureSpreadResolved(binding)) if (hasAnyMemberAccess(binding)) {
7172
- let kept = void 0;
7173
- binding.noSerialize = false;
7174
- forEach(binding.noSerializeProperties, (property) => {
7175
- if (!isPropertyMemberAccessed(binding, property)) kept = push(kept, property);
7176
- });
7177
- binding.noSerializeProperties = kept;
7178
- } else binding.noSerializeProperties = void 0;
7179
- else {
7180
- binding.noSerialize = false;
7181
- binding.noSerializeProperties = void 0;
7182
- }
7183
- }
7184
7268
  forEachSection(finalizeTagDownstreams);
7185
7269
  for (const binding of bindings) {
7186
7270
  const { name, section } = binding;
@@ -7190,9 +7274,9 @@ function finalizeReferences() {
7190
7274
  }
7191
7275
  if (binding.type !== 0) {
7192
7276
  resolveBindingSources(binding);
7193
- forEach(binding.assignmentSections, (assignedSection) => {
7277
+ forEach(binding.assignments, ({ section: assignedSection }) => {
7194
7278
  setReadsOwner(assignedSection, section);
7195
- addOwnerSerializeReason(assignedSection, section, true);
7279
+ addOwnerSerializeReason(assignedSection, section, FORCED);
7196
7280
  });
7197
7281
  let bindingNames = bindingNamesBySection.get(section);
7198
7282
  if (!bindingNames) {
@@ -7206,7 +7290,7 @@ function finalizeReferences() {
7206
7290
  forEach(binding.hoists, (hoistSection) => {
7207
7291
  if (!highestHoistSection || hoistSection.depth < highestHoistSection.depth) highestHoistSection = hoistSection;
7208
7292
  hoistSection.hoistedTo = bindingUtil.add(hoistSection.hoistedTo, binding);
7209
- addSerializeReason(binding.section, true, binding);
7293
+ addSerializeReason(binding.section, FORCED, binding);
7210
7294
  });
7211
7295
  binding.section.hoisted = bindingUtil.add(binding.section.hoisted, binding);
7212
7296
  let currentSection = binding.section.parent;
@@ -7229,21 +7313,20 @@ function finalizeReferences() {
7229
7313
  section.referencedClosures = bindingUtil.add(section.referencedClosures, canonicalUpstreamAlias);
7230
7314
  }
7231
7315
  setReadsOwner(section, canonicalUpstreamAlias.section);
7232
- if (isEffect) addOwnerSerializeReason(section, canonicalUpstreamAlias.section, true);
7233
- addOwnerSerializeReason(section, canonicalUpstreamAlias.section, canonicalUpstreamAlias.sources);
7316
+ addOwnerSerializeReason(section, canonicalUpstreamAlias.section, isEffect ? mergeSources(FORCED, canonicalUpstreamAlias.sources) : canonicalUpstreamAlias.sources);
7234
7317
  }
7235
7318
  }
7236
7319
  }
7237
7320
  }
7238
7321
  forEachSection((section) => {
7239
- if (section.isHoistThrough) addSerializeReason(section, true);
7322
+ if (section.isHoistThrough) addSerializeReason(section, FORCED);
7240
7323
  forEach(section.referencedHoists, (hoistedBinding) => {
7241
7324
  setReadsOwner(section, hoistedBinding.section);
7242
- addOwnerSerializeReason(section, hoistedBinding.section, true);
7325
+ addOwnerSerializeReason(section, hoistedBinding.section, FORCED);
7243
7326
  });
7244
7327
  if (section.parent && section.isBranch && section.sectionAccessor && section.upstreamExpression) {
7245
- if (section.isHoistThrough || section.hoisted) addSerializeReason(section, true, kBranchSerializeReason);
7246
- addSerializeReason(section, getSerializeSourcesForRef(getDirectClosures(section)), kBranchSerializeReason);
7328
+ const closureSources = getSerializeSourcesForRef(getDirectClosures(section));
7329
+ addSerializeReason(section, section.isHoistThrough || section.hoisted ? mergeSources(FORCED, closureSources) : closureSources, kBranchSerializeReason);
7247
7330
  addSerializeExpr(section, section.upstreamExpression, kBranchSerializeReason);
7248
7331
  addSerializeExpr(section.parent, section.upstreamExpression, section.sectionAccessor.binding);
7249
7332
  }
@@ -7282,8 +7365,7 @@ function finalizeReferences() {
7282
7365
  else if (upstreamReason) branchesSources = mergeSources(branchesSources, upstreamReason);
7283
7366
  currentSection = currentSection.parent;
7284
7367
  }
7285
- const branchesReason = branchesForced || branchesSources;
7286
- if (branchesForced) addSerializeReason(sourceSection, branchesSources, closure);
7368
+ const branchesReason = branchesForced ? mergeSources(FORCED, branchesSources) : branchesSources;
7287
7369
  addSerializeReason(sourceSection, branchesReason, closure);
7288
7370
  addSerializeReason(sourceSection, getSerializeReason(sourceSection, closure));
7289
7371
  if (isDynamicClosure(section, closure)) {
@@ -7296,22 +7378,15 @@ function finalizeReferences() {
7296
7378
  });
7297
7379
  });
7298
7380
  finalizeFunctionRegistry();
7299
- const referencedExprs = /* @__PURE__ */ new Set();
7300
- for (const binding of bindings) for (const expr of binding.reads) referencedExprs.add(expr);
7301
- for (const expr of referencedExprs) {
7302
- const exprFnReads = fnReadsByExpression.get(expr);
7303
- if (exprFnReads) {
7304
- for (const fn of exprFnReads.keys()) if (fn.registerReason) {
7305
- forEach(fn.referencedBindingsInFunction, (binding) => {
7306
- addSerializeReason(binding.section, fn.registerReason, binding);
7307
- if (binding.section !== fn.section) addOwnerSerializeReason(fn.section, binding.section, fn.registerReason);
7308
- });
7309
- forEach(fn.constantBindingsInFunction, (binding) => {
7310
- addSerializeReason(binding.section, fn.registerReason, binding);
7311
- if (binding.section !== fn.section) addOwnerSerializeReason(fn.section, binding.section, fn.registerReason);
7312
- });
7313
- }
7314
- }
7381
+ for (const exprFnReads of fnReadsByExpression.values()) for (const fn of exprFnReads.keys()) if (fn.registerReason) {
7382
+ forEach(fn.referencedBindingsInFunction, (binding) => {
7383
+ addSerializeReason(binding.section, fn.registerReason, binding);
7384
+ if (binding.section !== fn.section) addOwnerSerializeReason(fn.section, binding.section, fn.registerReason);
7385
+ });
7386
+ forEach(fn.constantBindingsInFunction, (binding) => {
7387
+ addSerializeReason(binding.section, fn.registerReason, binding);
7388
+ if (binding.section !== fn.section) addOwnerSerializeReason(fn.section, binding.section, fn.registerReason);
7389
+ });
7315
7390
  }
7316
7391
  forEachSection(finalizeParamSerializeReasonGroups);
7317
7392
  forEachSectionReverse((section) => {
@@ -7323,10 +7398,11 @@ function finalizeReferences() {
7323
7398
  const { id, bindings } = section;
7324
7399
  const isOwnedBinding = ({ section }) => section.id === id;
7325
7400
  const ownedBindings = filter(bindings, isOwnedBinding);
7401
+ const intersectionSources = /* @__PURE__ */ new Map();
7326
7402
  const intersections = (intersectionsBySection.get(section) || []).filter((intersection) => {
7327
- const collapseSource = getCollapsibleIntersectionSource(intersection, section);
7328
- if (collapseSource) collapsedIntersectionSource.set(intersection, collapseSource);
7329
- return !collapseSource;
7403
+ const source = getIntersectionSource(intersection, section, intersectionSources);
7404
+ if (source) intersectionMeta.set(intersection, { source });
7405
+ return !source;
7330
7406
  });
7331
7407
  let anchors;
7332
7408
  if (intersections.length) {
@@ -7344,31 +7420,29 @@ function finalizeReferences() {
7344
7420
  let intersectionIndex = 0;
7345
7421
  let nextId = 0;
7346
7422
  let intersection;
7423
+ const assignIntersectionId = (intersection) => {
7424
+ intersectionMeta.set(intersection, {
7425
+ source: void 0,
7426
+ id: nextId++,
7427
+ scopeOffset: getMaxOwnSourceOffset(intersection, section)
7428
+ });
7429
+ };
7347
7430
  forEach(ownedBindings, (binding) => {
7348
7431
  if (binding.type !== 0) while (intersectionIndex < intersections.length && !anchors.get(intersection = intersections[intersectionIndex])) {
7349
7432
  intersectionIndex++;
7350
- intersectionMeta.set(intersection, {
7351
- id: nextId++,
7352
- scopeOffset: getMaxOwnSourceOffset(intersection, section)
7353
- });
7433
+ assignIntersectionId(intersection);
7354
7434
  }
7355
7435
  binding.id = nextId++;
7356
7436
  nextId += binding.reserveSize;
7357
7437
  while (intersectionIndex < intersections.length && anchors.get(intersection = intersections[intersectionIndex]) === binding) {
7358
7438
  intersectionIndex++;
7359
- intersectionMeta.set(intersection, {
7360
- id: nextId++,
7361
- scopeOffset: getMaxOwnSourceOffset(intersection, section)
7362
- });
7439
+ assignIntersectionId(intersection);
7363
7440
  }
7364
7441
  });
7365
7442
  while (intersectionIndex < intersections.length) {
7366
7443
  intersection = intersections[intersectionIndex];
7367
7444
  intersectionIndex++;
7368
- intersectionMeta.set(intersection, {
7369
- id: nextId++,
7370
- scopeOffset: getMaxOwnSourceOffset(intersection, section)
7371
- });
7445
+ assignIntersectionId(intersection);
7372
7446
  }
7373
7447
  forEach(ownedBindings, (binding) => {
7374
7448
  if (binding.closureSections) closureAccessorIds.set(binding, nextId++);
@@ -7402,13 +7476,20 @@ function getMaxOwnSourceOffset(intersection, section) {
7402
7476
  }
7403
7477
  const intersectionMeta = /* @__PURE__ */ new WeakMap();
7404
7478
  const closureAccessorIds = /* @__PURE__ */ new WeakMap();
7405
- const collapsedIntersectionSource = /* @__PURE__ */ new WeakMap();
7406
- function getCollapsibleIntersectionSource(intersection, section) {
7479
+ function getIntersectionSource(intersection, section, resolved) {
7480
+ if (!resolved.has(intersection)) {
7481
+ resolved.set(intersection, void 0);
7482
+ resolved.set(intersection, resolveIntersectionSource(intersection, section, resolved));
7483
+ }
7484
+ return resolved.get(intersection);
7485
+ }
7486
+ function resolveIntersectionSource(intersection, section, resolved) {
7407
7487
  let sources;
7408
7488
  for (const member of intersection) {
7409
7489
  if (!member.sources) return void 0;
7410
- const isDirectAlias = member.upstreamAlias && member.property === void 0 && member.excludeProperties === void 0;
7411
- if (member.section !== section || isDirectAlias) return void 0;
7490
+ if (member.section !== section || isDirectAlias(member)) return void 0;
7491
+ const upstream = getUpstreamIntersection(member);
7492
+ if (upstream && upstream !== intersection && !getIntersectionSource(upstream, section, resolved)) return;
7412
7493
  sources = mergeSources(sources, member.sources);
7413
7494
  }
7414
7495
  if (!sources || sources.state && sources.param) return;
@@ -7434,7 +7515,7 @@ function resolveBindingSources(binding) {
7434
7515
  if (aliasRoot) {
7435
7516
  resolveBindingSources(aliasRoot);
7436
7517
  binding.sources = aliasRoot.sources;
7437
- } else if (binding.assignmentSections) binding.sources = createSources(binding, void 0);
7518
+ } else if (binding.assignments) binding.sources = createSources(binding, void 0);
7438
7519
  else resolveDerivedSources(binding);
7439
7520
  return;
7440
7521
  }
@@ -7466,34 +7547,36 @@ function getAliasRoot(binding) {
7466
7547
  return alias;
7467
7548
  }
7468
7549
  function resolveDerivedSources(binding) {
7469
- const bindingValueExprs = getBindingValueExprs();
7470
- const exprs = bindingValueExprs.get(binding);
7471
- bindingValueExprs.delete(binding);
7550
+ const exprs = getBindingValueExprs().get(binding);
7472
7551
  if (exprs === void 0 || exprs === true) binding.sources = createSources(binding, void 0);
7473
7552
  else if (exprs) {
7474
- const seen = /* @__PURE__ */ new Set();
7553
+ let refs;
7475
7554
  forEach(exprs, (expr) => {
7476
- if (isReferencedExtra(expr)) forEach(expr.referencedBindings, (ref) => {
7477
- if (!seen.has(ref)) {
7478
- seen.add(ref);
7479
- resolveBindingSources(ref);
7480
- binding.sources = mergeSources(binding.sources, ref.sources);
7481
- }
7482
- });
7555
+ if (isReferencedExtra(expr) && !expr.initialValue) refs = bindingUtil.union(refs, expr.referencedBindings);
7556
+ });
7557
+ forEach(refs, (ref) => {
7558
+ resolveBindingSources(ref);
7559
+ binding.sources = mergeSources(binding.sources, ref.sources);
7483
7560
  });
7561
+ binding.upstreamIntersection = Array.isArray(refs) ? refs : refs && getUpstreamIntersection(refs);
7484
7562
  }
7485
7563
  }
7486
- function createSources(state, param, global) {
7564
+ function getUpstreamIntersection(binding) {
7565
+ return (getAliasRoot(binding) || binding).upstreamIntersection;
7566
+ }
7567
+ function createSources(state, param, global, forced) {
7487
7568
  /* v8 ignore next 6 -- every caller passes at least one source */
7488
- if (!(state || param || global)) throw new Error("Cannot create a serialize reason that does not reference state, a param, or $global.");
7569
+ if (!(state || param || global || forced)) throw new Error("Cannot create a serialize reason that does not reference state, a param, or $global.");
7489
7570
  return {
7490
7571
  state,
7491
7572
  param,
7492
- global
7573
+ global,
7574
+ forced
7493
7575
  };
7494
7576
  }
7495
7577
  function compareSources(a, b) {
7496
7578
  let delta;
7579
+ if (a.forced !== b.forced) return a.forced ? 1 : -1;
7497
7580
  if (a.global !== b.global) return a.global ? 1 : -1;
7498
7581
  if (a.param) {
7499
7582
  if (!b.param) return 1;
@@ -7508,12 +7591,12 @@ function compareSources(a, b) {
7508
7591
  function mergeSources(a, b) {
7509
7592
  if (!a) return b;
7510
7593
  if (!b) return a;
7511
- if (a.state === b.state && a.param === b.param && a.global === b.global) return a;
7512
- return createSources(bindingUtil.union(a.state, b.state), unionParamSources(a.param, b.param), a.global || b.global);
7594
+ if (a.state === b.state && a.param === b.param && a.global === b.global && a.forced === b.forced) return a;
7595
+ return createSources(bindingUtil.union(a.state, b.state), unionParamSources(a.param, b.param), a.global || b.global, a.forced || b.forced);
7513
7596
  }
7514
7597
  function unionParamSources(a, b) {
7515
7598
  const merged = bindingUtil.union(a, b);
7516
- if (merged && Array.isArray(merged)) return filter(merged, (binding) => {
7599
+ if (merged && Array.isArray(merged)) return bindingUtil.filter(merged, (binding) => {
7517
7600
  let alias = binding.upstreamAlias;
7518
7601
  while (alias) {
7519
7602
  if (bindingUtil.has(merged, alias)) return false;
@@ -7529,6 +7612,7 @@ const bindingUtil = new Sorted(function compareBindings(a, b) {
7529
7612
  const propsUtil = new Sorted(function compareProps(a, b) {
7530
7613
  return a < b ? -1 : a > b ? 1 : 0;
7531
7614
  });
7615
+ const [getAssignments] = createProgramState(() => []);
7532
7616
  const [getReadsByExpression] = createProgramState(() => /* @__PURE__ */ new Map());
7533
7617
  const [getFunctionReadsByExpression] = createProgramState(() => /* @__PURE__ */ new Map());
7534
7618
  const [getReferenceFinalizers] = createProgramState(() => []);
@@ -7553,20 +7637,43 @@ function addRead(exprExtra, extra, binding, section, getter) {
7553
7637
  readsByExpression.set(exprExtra, push(readsByExpression.get(exprExtra), read));
7554
7638
  return read;
7555
7639
  }
7640
+ function isEmitted(exprExtra) {
7641
+ return !getCanonicalExtra(exprExtra).pruned;
7642
+ }
7643
+ function inEmittedExpr({ exprRoot }) {
7644
+ return isEmitted(exprRoot);
7645
+ }
7646
+ function isDroppableValue(expr) {
7647
+ return !!expr.pure && !expr.merged && !expr.pruned;
7648
+ }
7649
+ function dropPureExtra(expr) {
7650
+ if (isDroppableValue(expr) && every(expr.downstream, isPrunedBinding)) dropExtra(expr);
7651
+ }
7652
+ function isPrunedBinding(binding) {
7653
+ return !!binding.pruned;
7654
+ }
7556
7655
  function dropNodes(node) {
7557
7656
  if (Array.isArray(node)) for (const item of node) dropExtra(item.extra ??= {});
7558
7657
  else dropExtra(node.extra ??= {});
7559
7658
  }
7659
+ function untrackNode(node) {
7660
+ untrackExtra(node.extra ??= {});
7661
+ }
7560
7662
  function dropExtra(exprExtra) {
7663
+ exprExtra.pruned = true;
7664
+ untrackExtra(exprExtra);
7665
+ }
7666
+ function untrackExtra(exprExtra) {
7561
7667
  /* v8 ignore next 3 -- a merged reference is never dropped */
7562
7668
  if (exprExtra.merged) throw new Error("Cannot drop a merged reference");
7563
7669
  const readsByExpr = getReadsByExpression();
7564
7670
  const reads = readsByExpr.get(exprExtra);
7565
- exprExtra.pruned = true;
7566
7671
  if (reads) {
7567
7672
  readsByExpr.delete(exprExtra);
7673
+ getFunctionReadsByExpression().delete(exprExtra);
7568
7674
  forEach(reads, (read) => {
7569
7675
  read.binding.reads.delete(exprExtra);
7676
+ if (!exprExtra.pruned) read.binding.untracked = true;
7570
7677
  });
7571
7678
  }
7572
7679
  }
@@ -7583,8 +7690,11 @@ function addReadToExpression(root, binding, getter) {
7583
7690
  const fnRoot = getFnRoot(root);
7584
7691
  const exprRoot = getExprRoot(fnRoot || root);
7585
7692
  const section = getOrCreateSection(exprRoot);
7586
- const exprExtra = getCanonicalExtra(exprRoot.node.extra ??= { section });
7587
- const read = addRead(exprExtra, node.extra ??= {}, binding, section, getter);
7693
+ const rootExtra = exprRoot.node.extra ??= { section };
7694
+ const exprExtra = getCanonicalExtra(rootExtra);
7695
+ const extra = node.extra ??= {};
7696
+ extra.exprRoot = rootExtra;
7697
+ const read = addRead(exprExtra, extra, binding, section, getter);
7588
7698
  if (!fnRoot && isSerializedChangeHandlerRead(exprRoot)) read.serializedValue = true;
7589
7699
  const { parent } = root;
7590
7700
  if (parent.type === "BinaryExpression" && (parent.operator === "===" || parent.operator === "!==")) read.comparedTo = parent.left === node ? parent.right : parent.left;
@@ -7600,14 +7710,23 @@ function addReadToExpression(root, binding, getter) {
7600
7710
  if (!exprFnReads) fnReadsByExpr.set(exprExtra, exprFnReads = /* @__PURE__ */ new Map());
7601
7711
  const fnExtra = fnRoot.node.extra ??= {};
7602
7712
  fnExtra.section = section;
7713
+ fnExtra.exprRoot = rootExtra;
7603
7714
  exprFnReads.set(fnExtra, push(exprFnReads.get(fnExtra), read));
7604
7715
  }
7605
7716
  }
7606
7717
  function getCanonicalBinding(binding) {
7607
7718
  const alias = binding.upstreamAlias;
7608
- if (alias && binding.property === void 0 && binding.excludeProperties === void 0) return alias;
7719
+ if (alias && isDirectAlias(binding)) return alias;
7609
7720
  return binding;
7610
7721
  }
7722
+ function someAlias(binding, test, arg, directOnly) {
7723
+ if (test(binding, arg)) return true;
7724
+ for (const alias of binding.aliases) if ((!directOnly || isDirectAlias(alias)) && someAlias(alias, test, arg, directOnly)) return true;
7725
+ return false;
7726
+ }
7727
+ function isDirectAlias(binding) {
7728
+ return binding.upstreamAlias !== void 0 && binding.property === void 0 && binding.excludeProperties === void 0;
7729
+ }
7611
7730
  function getAllTagReferenceNodes(tag, referenceNodes = []) {
7612
7731
  if (tag.arguments) for (const arg of tag.arguments) referenceNodes.push(arg);
7613
7732
  for (const attr of tag.attributes) referenceNodes.push(attr.value);
@@ -7732,20 +7851,22 @@ function getReadReplacement(node, signal) {
7732
7851
  if (readBinding.getters.has(readBinding.section)) replacement = getBindingGetterIdentifier(readBinding, readBinding.section);
7733
7852
  } else if (readBinding.name !== node.name) node.name = readBinding.name;
7734
7853
  } else {
7735
- const props = read.props ? Array.isArray(read.props) ? read.props.slice() : [read.props] : [];
7854
+ const { props } = read;
7855
+ let remaining = size(props);
7736
7856
  let curNode = node;
7737
7857
  let curBinding = readBinding;
7738
7858
  let replaceMember;
7739
7859
  if (isOutputDOM()) if (signal?.referencedBindings === readBinding && !signal.hasSideEffect) replacement = getSignalValueIdentifier(signal);
7740
7860
  else replacement = createScopeReadExpression(readBinding, extra.section);
7741
7861
  else replacement = _marko_compiler.types.identifier(readBinding.name);
7742
- while (props.length && (curNode.type === "MemberExpression" || curNode.type === "OptionalMemberExpression")) {
7743
- const prop = props.pop();
7862
+ while (remaining && (curNode.type === "MemberExpression" || curNode.type === "OptionalMemberExpression")) {
7863
+ const prop = at(props, --remaining);
7744
7864
  if (getMemberExpressionPropString(curNode) !== prop) break;
7745
7865
  replaceMember = curNode;
7746
7866
  curNode = curNode.object;
7747
7867
  }
7748
- for (const prop of props) {
7868
+ for (let i = 0; i < remaining; i++) {
7869
+ const prop = at(props, i);
7749
7870
  if (curBinding) curBinding = curBinding.propertyAliases.get(prop);
7750
7871
  replacement = toMemberExpression(replacement, prop, !!curBinding?.nullable);
7751
7872
  }
@@ -7762,45 +7883,62 @@ function getReadReplacement(node, signal) {
7762
7883
  } else if (binding && node.type == "Identifier" && node.name !== binding.name) node.name = binding.name;
7763
7884
  }
7764
7885
  function isInvokeOnlyBinding(binding) {
7765
- if (binding.assignmentSections || binding.hoists || binding.getters.size || binding.propertyAliases.size || binding.excludeProperties) return false;
7766
- for (const expr of binding.reads) if (!expr.invokeOnly) return false;
7767
- for (const alias of binding.aliases) if (!isInvokeOnlyBinding(alias)) return false;
7768
- return true;
7886
+ return !someAlias(binding, isReadBeyondInvoking, void 0);
7887
+ }
7888
+ function isReadBeyondInvoking(binding) {
7889
+ if (binding.assignments || binding.hoists || binding.getters.size || binding.propertyAliases.size || binding.excludeProperties) return true;
7890
+ for (const expr of binding.reads) if (!expr.invokeOnly) return true;
7891
+ return false;
7769
7892
  }
7770
7893
  function hasNonConstantPropertyAlias(ref) {
7771
7894
  for (const alias of ref.propertyAliases.values()) if (alias.type !== 6) return true;
7772
7895
  return false;
7773
7896
  }
7774
- function pruneBinding(binding) {
7897
+ function pruneBinding(binding, settled) {
7775
7898
  if (binding.pruned !== void 0) return binding.pruned;
7899
+ if (settled) {
7900
+ binding.pruned = false;
7901
+ for (const read of binding.reads) if (isDroppableValue(read)) forEach(read.downstream, pruneSettledBinding);
7902
+ forEach(binding.assignments, pruneSettledWriter);
7903
+ }
7776
7904
  for (const read of binding.reads) {
7777
7905
  let upstream = binding.upstreamAlias;
7778
7906
  while (upstream && !upstream.reads.has(read)) upstream = upstream.upstreamAlias;
7779
7907
  if (upstream) binding.reads.delete(read);
7780
7908
  }
7781
7909
  let shouldPrune = !binding.reads.size && !binding.reserveSize;
7782
- for (const alias of binding.aliases) if (pruneBinding(alias)) binding.aliases.delete(alias);
7910
+ for (const alias of binding.aliases) if (pruneBinding(alias, settled)) binding.aliases.delete(alias);
7783
7911
  else if (alias.type !== 6) shouldPrune = false;
7784
- for (const [key, alias] of binding.propertyAliases) if (pruneBinding(alias)) binding.propertyAliases.delete(key);
7912
+ for (const [key, alias] of binding.propertyAliases) if (pruneBinding(alias, settled)) binding.propertyAliases.delete(key);
7785
7913
  else if (alias.type !== 6) shouldPrune = false;
7786
- binding.pruned = shouldPrune;
7914
+ if (settled) {
7915
+ binding.pruned = shouldPrune;
7916
+ if (shouldPrune && !binding.untracked && !some(binding.assignments, inEmittedExpr)) {
7917
+ const exprs = getBindingValueExprs().get(binding);
7918
+ if (exprs && exprs !== true) forEach(exprs, dropPureExtra);
7919
+ }
7920
+ }
7787
7921
  return shouldPrune;
7788
7922
  }
7923
+ function pruneSettledBinding(binding) {
7924
+ pruneBinding(binding, true);
7925
+ }
7926
+ function pruneSettledWriter({ exprRoot }) {
7927
+ if (isDroppableValue(exprRoot)) forEach(exprRoot.downstream, pruneSettledBinding);
7928
+ }
7789
7929
  function resolveReferencedBindingsInFunction(refs, reads) {
7790
7930
  let referencedBindings;
7791
7931
  let constantBindings;
7792
- if (reads) if (Array.isArray(reads)) for (const read of reads) {
7793
- const { getter, binding } = read;
7932
+ const closest = /* @__PURE__ */ new Set();
7933
+ forEach(reads, ({ getter, binding }) => {
7794
7934
  if (getter) {} else if (binding.type === 6) {
7795
7935
  if (bindingUtil.find(refs, binding)) constantBindings = bindingUtil.add(constantBindings, binding);
7796
- } else if (binding.type !== 0 && binding.type !== 7) referencedBindings = bindingUtil.add(referencedBindings, findClosestReference(read.binding, refs));
7797
- }
7798
- else {
7799
- const { getter, binding } = reads;
7800
- if (getter) {} else if (binding.type === 6) {
7801
- if (bindingUtil.find(refs, binding)) constantBindings = binding;
7802
- } else if (binding.type !== 0 && binding.type !== 7) referencedBindings = findClosestReference(binding, refs);
7803
- }
7936
+ } else if (binding.type !== 0 && binding.type !== 7) {
7937
+ const ref = findClosestReference(binding, refs);
7938
+ if (ref) closest.add(ref);
7939
+ }
7940
+ });
7941
+ if (closest.size) referencedBindings = bindingUtil.filter(refs, (ref) => closest.has(ref));
7804
7942
  return {
7805
7943
  referencedBindings,
7806
7944
  constantBindings
@@ -7970,6 +8108,12 @@ function createGetterRead(binding, props, getter) {
7970
8108
  function isReferencedExtra(extra) {
7971
8109
  return !!(extra && !extra.pruned && extra.section);
7972
8110
  }
8111
+ function hasResumableWriter(binding) {
8112
+ return some(binding.assignments, isResumableWriter);
8113
+ }
8114
+ function isResumableWriter({ exprRoot, fnRoot }) {
8115
+ return !!getCanonicalExtra(exprRoot).isEffect || isRegisteredFnExtra(fnRoot);
8116
+ }
7973
8117
  function isAssignedBindingExtra(extra) {
7974
8118
  return isReferencedExtra(extra) && extra.assignment !== void 0;
7975
8119
  }
@@ -7980,93 +8124,130 @@ function getCanonicalExtra(extra) {
7980
8124
  while (extra.merged) extra = extra.merged;
7981
8125
  return extra;
7982
8126
  }
7983
- const serializeReasonCache = /* @__PURE__ */ new WeakMap();
7984
- const registerReasonCache = /* @__PURE__ */ new WeakMap();
7985
- function getAllSerializeReasonsForExtra(extra, register) {
7986
- if (extra.isEffect || register && extra.dynamicTagInput) return true;
7987
- const cache = register ? registerReasonCache : serializeReasonCache;
7988
- let reason = cache.get(extra);
7989
- if (reason === false) return;
7990
- if (reason === void 0) {
7991
- if (extra === (0, _marko_compiler_babel_utils.getProgram)().node.extra?.section.returnValueExpr) reason = true;
7992
- else {
7993
- cache.set(extra, false);
7994
- forEach(extra.downstream, (binding) => {
7995
- let linked = getAllSerializeReasonsForBinding(binding, true, register);
7996
- if (linked && linked !== true) {
7997
- const exprs = extra.downstreamExprs;
7998
- if (exprs) linked = mapDownstreamReason(binding.section.program, linked, exprs);
7999
- }
8000
- reason = mergeSerializeReasons(reason, linked);
8001
- });
8002
- }
8003
- if (reason) cache.set(extra, reason);
8004
- }
8005
- return reason;
8127
+ const UNSERIALIZED = {
8128
+ reason: void 0,
8129
+ reads: void 0
8130
+ };
8131
+ const FORCED_SERIALIZATION = {
8132
+ reason: FORCED,
8133
+ reads: void 0
8134
+ };
8135
+ const extraSerialization = createCyclicMemo(computeExtraSerialization, UNSERIALIZED);
8136
+ const bindingSerialization = createCyclicPathMemo(computeBindingSerialization, UNSERIALIZED);
8137
+ function getAllSerializeReasonsForBinding(binding, properties) {
8138
+ return serializationForBinding(binding, properties).reason;
8139
+ }
8140
+ function getRegisterReasonForExtra(extra) {
8141
+ if (extra.forceRegister) return FORCED;
8142
+ const { reason, reads } = serializationForExtra(extra);
8143
+ return some(reads, isForceRegisterRead) ? FORCED : reason;
8144
+ }
8145
+ function isForceRegisterRead(read) {
8146
+ return !!read.forceRegister;
8147
+ }
8148
+ function serializationForExtra(extra) {
8149
+ if (extra.isEffect) return FORCED_SERIALIZATION;
8150
+ const serialization = extraSerialization(extra);
8151
+ const reads = isReferencedExtra(extra) ? addUnique(serialization.reads, extra) : serialization.reads;
8152
+ return reads === serialization.reads ? serialization : {
8153
+ reason: serialization.reason,
8154
+ reads
8155
+ };
8006
8156
  }
8007
- function getAllSerializeReasonsForBinding(binding, properties, register) {
8008
- const cache = register ? registerReasonCache : serializeReasonCache;
8009
- let reason = cache.get(binding);
8010
- if (reason === void 0) {
8011
- reason = getSerializeReason(binding.section, binding);
8012
- if (reason !== true) {
8013
- cache.set(binding, reason || false);
8014
- if (properties !== true && binding.upstreamAlias) reason = mergeSerializeReasons(reason, getAllSerializeReasonsForBinding(binding.upstreamAlias, binding.property, register));
8015
- if (reason !== true) {
8016
- for (const expr of binding.reads) {
8017
- reason = mergeSerializeReasons(reason, getAllSerializeReasonsForExtra(expr, register));
8018
- if (reason === true) break;
8019
- }
8020
- if (reason !== true) for (const alias of binding.aliases) {
8021
- reason = mergeSerializeReasons(reason, getAllSerializeReasonsForBinding(alias, properties, register));
8022
- if (reason === true) break;
8023
- }
8024
- }
8157
+ function serializationForBinding(binding, properties) {
8158
+ return bindingSerialization(binding, properties);
8159
+ }
8160
+ function computeExtraSerialization(extra) {
8161
+ return readSerialization(extra, void 0);
8162
+ }
8163
+ function readSerialization(extra, part) {
8164
+ if (extra === (0, _marko_compiler_babel_utils.getProgram)().node.extra?.section.returnValueExpr) return FORCED_SERIALIZATION;
8165
+ let serialization = UNSERIALIZED;
8166
+ forEach(extra.downstream, (binding) => {
8167
+ if (!isPartOf(binding, part)) serialization = mergeSerialization(serialization, downstreamSerialization(extra, binding));
8168
+ });
8169
+ return serialization;
8170
+ }
8171
+ function downstreamSerialization(extra, binding) {
8172
+ const linked = serializationForBinding(binding, true);
8173
+ const exprs = extra.downstreamExprs;
8174
+ return linked.reason && exprs ? {
8175
+ reason: mapParamReason(binding.section.program, linked.reason, exprs, true),
8176
+ reads: linked.reads
8177
+ } : linked;
8178
+ }
8179
+ function isPartOf(binding, value) {
8180
+ return !!value && binding.upstreamAlias === value && !isDirectAlias(binding);
8181
+ }
8182
+ function computeBindingSerialization(binding, properties) {
8183
+ let reason = getSerializeReason(binding.section, binding);
8184
+ let serialization = reason ? {
8185
+ reason,
8186
+ reads: void 0
8187
+ } : UNSERIALIZED;
8188
+ const upstream = binding.upstreamAlias;
8189
+ if (properties !== true && upstream && !upstream.noSerialize && !propsUtil.has(upstream.noSerializeProperties, binding.property)) serialization = mergeSerialization(serialization, serializationForBinding(upstream, properties === void 0 ? binding.property : concat(binding.property, properties)));
8190
+ for (const expr of binding.reads) {
8191
+ if (expr.isEffect) {
8192
+ serialization = mergeSerialization(serialization, FORCED_SERIALIZATION);
8193
+ continue;
8025
8194
  }
8026
- if (reason) cache.set(binding, reason);
8195
+ const reads = addUnique(serialization.reads, expr);
8196
+ if (reads !== serialization.reads) serialization = {
8197
+ reason: serialization.reason,
8198
+ reads
8199
+ };
8200
+ serialization = mergeSerialization(serialization, readSerialization(expr, binding));
8027
8201
  }
8028
- if (reason === false) reason = void 0;
8029
- if (properties !== void 0) if (properties === true) {
8030
- if (reason !== true) for (const propBinding of binding.propertyAliases.values()) {
8031
- reason = mergeSerializeReasons(reason, getAllSerializeReasonsForBinding(propBinding, true, register));
8032
- if (reason === true) break;
8033
- }
8034
- } else {
8035
- let property;
8036
- let rest;
8037
- if (Array.isArray(properties)) {
8038
- property = properties[0];
8039
- rest = properties.length === 2 ? properties[1] : properties.slice(1);
8040
- } else property = properties;
8041
- if (includes(binding.excludeProperties, property)) reason = void 0;
8042
- else {
8043
- const propBinding = binding.propertyAliases.get(property);
8044
- if (propBinding) reason = mergeSerializeReasons(reason, getAllSerializeReasonsForBinding(propBinding, rest, register));
8045
- if (reason !== true) for (const alias of binding.aliases) {
8046
- const propBinding = alias.propertyAliases.get(property);
8047
- if (propBinding) {
8048
- reason = mergeSerializeReasons(reason, getAllSerializeReasonsForBinding(propBinding, rest, register));
8049
- if (reason === true) break;
8050
- }
8051
- }
8052
- }
8202
+ for (const alias of binding.aliases) serialization = mergeSerialization(serialization, serializationForBinding(alias, properties));
8203
+ if (properties === void 0) return serialization;
8204
+ if (properties === true) {
8205
+ for (const propBinding of binding.propertyAliases.values()) serialization = mergeSerialization(serialization, serializationForBinding(propBinding, true));
8206
+ return serialization;
8053
8207
  }
8054
- return reason;
8208
+ const property = first(properties);
8209
+ if (propsUtil.has(binding.excludeProperties, property)) return UNSERIALIZED;
8210
+ const propBinding = binding.propertyAliases.get(property);
8211
+ if (propBinding) serialization = mergeSerialization(serialization, serializationForBinding(propBinding, rest(properties)));
8212
+ for (const alias of binding.aliases) {
8213
+ const propBinding = alias.propertyAliases.get(property);
8214
+ if (propBinding) serialization = mergeSerialization(serialization, serializationForBinding(propBinding, rest(properties)));
8215
+ }
8216
+ return serialization;
8217
+ }
8218
+ function mergeSerialization(a, b) {
8219
+ if (a === UNSERIALIZED) return b;
8220
+ if (b === UNSERIALIZED) return a;
8221
+ const reason = mergeSources(a.reason, b.reason);
8222
+ let reads = a.reads;
8223
+ forEach(b.reads, (read) => {
8224
+ reads = addUnique(reads, read);
8225
+ });
8226
+ if (reason === a.reason && reads === a.reads) return a;
8227
+ if (reason === b.reason && reads === b.reads) return b;
8228
+ return {
8229
+ reason,
8230
+ reads
8231
+ };
8055
8232
  }
8056
8233
  function isPureSpreadResolved(binding) {
8057
- for (const read of binding.reads) if (!read.nativeTagSpread || read.nativeTagSpreadMerged) return false;
8058
- for (const alias of binding.aliases) if (!isPureSpreadResolved(alias)) return false;
8059
- return true;
8234
+ return !someAlias(binding, hasReadBeyondSpreading, void 0);
8060
8235
  }
8061
- function hasAnyMemberAccess(binding) {
8062
- if (binding.propertyAliases.size) return true;
8063
- for (const alias of binding.aliases) if (hasAnyMemberAccess(alias)) return true;
8236
+ function hasReadBeyondSpreading(binding) {
8237
+ for (const read of binding.reads) if (!read.nativeTagSpread || read.nativeTagSpreadMerged) return true;
8064
8238
  return false;
8065
8239
  }
8240
+ function hasAnyMemberAccess(binding) {
8241
+ return someAlias(binding, hasPropertyAliases, void 0);
8242
+ }
8243
+ function hasPropertyAliases(binding) {
8244
+ return binding.propertyAliases.size > 0;
8245
+ }
8066
8246
  function isPropertyMemberAccessed(binding, property) {
8067
- if (binding.propertyAliases.has(property)) return true;
8068
- for (const alias of binding.aliases) if (isPropertyMemberAccessed(alias, property)) return true;
8069
- return false;
8247
+ return someAlias(binding, hasPropertyAlias, property);
8248
+ }
8249
+ function hasPropertyAlias(binding, property) {
8250
+ return binding.propertyAliases.has(property);
8070
8251
  }
8071
8252
  function addNumericPropertiesUntil(props, len) {
8072
8253
  let result = props;
@@ -8074,11 +8255,7 @@ function addNumericPropertiesUntil(props, len) {
8074
8255
  return result;
8075
8256
  }
8076
8257
  function setReadsOwner(from, to) {
8077
- let cur = from;
8078
- while (cur !== to && cur.parent) {
8079
- cur.readsOwner = true;
8080
- cur = cur.parent;
8081
- }
8258
+ for (const section of ancestorSections(from, to)) section.readsOwner = true;
8082
8259
  }
8083
8260
  function mapParamReasonToExpr(exprs, reason) {
8084
8261
  if (reason) {
@@ -8109,7 +8286,7 @@ function mapParamBindingToExpr(exprs, binding) {
8109
8286
  if (isWholeAlias) {
8110
8287
  let result = curExpr.value;
8111
8288
  if (curExpr.known) {
8112
- for (const key in curExpr.known) if (!includes(binding.excludeProperties, key)) result = concat(result, curExpr.known[key].value);
8289
+ for (const key in curExpr.known) if (!propsUtil.has(binding.excludeProperties, key)) result = concat(result, curExpr.known[key].value);
8113
8290
  }
8114
8291
  return result;
8115
8292
  }
@@ -8117,7 +8294,6 @@ function mapParamBindingToExpr(exprs, binding) {
8117
8294
  }
8118
8295
  //#endregion
8119
8296
  //#region src/translator/core/await.ts
8120
- const kDOMBinding$2 = Symbol("await tag dom binding");
8121
8297
  var await_default = {
8122
8298
  analyze(tag) {
8123
8299
  (0, _marko_compiler_babel_utils.assertNoVar)(tag);
@@ -8129,7 +8305,7 @@ var await_default = {
8129
8305
  const section = getOrCreateSection(tag);
8130
8306
  const [valueAttr] = node.attributes;
8131
8307
  const tagExtra = tag.node.extra ??= {};
8132
- tagExtra[kDOMBinding$2] = createBinding("#text", 0, section);
8308
+ tagExtra.nodeBinding = createBinding("#text", 0, section);
8133
8309
  if (!valueAttr) throw tag.get("name").buildCodeFrameError("The [`<await>` tag](https://markojs.com/docs/reference/core-tag#await) requires a [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
8134
8310
  if (node.attributes.length > 1 || !_marko_compiler.types.isMarkoAttribute(valueAttr) || valueAttr.name !== "value") throw tag.get("name").buildCodeFrameError("The [`<await>` tag](https://markojs.com/docs/reference/core-tag#await) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
8135
8311
  if (!node.body.body.length) throw tag.get("name").buildCodeFrameError("The [`<await>` tag](https://markojs.com/docs/reference/core-tag#await) requires [content](https://markojs.com/docs/reference/language#tag-content).");
@@ -8157,7 +8333,7 @@ var await_default = {
8157
8333
  exit(tag) {
8158
8334
  const { node } = tag;
8159
8335
  const [valueAttr] = node.attributes;
8160
- const nodeRef = node.extra[kDOMBinding$2];
8336
+ const nodeRef = node.extra.nodeBinding;
8161
8337
  const tagBody = tag.get("body");
8162
8338
  const section = getSection(tag);
8163
8339
  const bodySection = getSectionForBody(tagBody);
@@ -8177,7 +8353,7 @@ var await_default = {
8177
8353
  },
8178
8354
  exit(tag) {
8179
8355
  const { node } = tag;
8180
- const nodeRef = node.extra[kDOMBinding$2];
8356
+ const nodeRef = node.extra.nodeBinding;
8181
8357
  const section = getSection(tag);
8182
8358
  const bodySection = getSectionForBody(tag.get("body"));
8183
8359
  const signal = getSignal(section, nodeRef, "await_promise");
@@ -8260,7 +8436,7 @@ var const_default = {
8260
8436
  if (node.attributes.length > 1 || !_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default && valueAttr.name !== "value") throw tag.get("name").buildCodeFrameError("The [`<const>` tag](https://markojs.com/docs/reference/core-tag#const) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
8261
8437
  const valueExtra = evaluate(valueAttr.value);
8262
8438
  const upstreamAlias = _marko_compiler.types.isIdentifier(valueAttr.value) ? tag.scope.getBinding(valueAttr.value.name)?.identifier.extra?.binding : void 0;
8263
- if (upstreamAlias) dropNodes(valueAttr.value);
8439
+ if (upstreamAlias) untrackNode(valueAttr.value);
8264
8440
  const binding = trackVarReferences(tag, 5, upstreamAlias);
8265
8441
  if (binding) {
8266
8442
  assertNoTagVarMutation(tag);
@@ -8275,14 +8451,14 @@ var const_default = {
8275
8451
  const { node } = tag;
8276
8452
  const [valueAttr] = node.attributes;
8277
8453
  const { value } = valueAttr;
8454
+ const varBinding = node.var.extra?.binding;
8278
8455
  if (isOutputDOM()) {
8279
8456
  const section = getSection(tag);
8280
- const varBinding = node.var.extra?.binding;
8281
- if (varBinding && !varBinding.upstreamAlias) {
8457
+ if (varBinding && !varBinding.upstreamAlias && !value.extra?.pruned) {
8282
8458
  const derivation = initValue(varBinding);
8283
8459
  addValue(section, value.extra?.referencedBindings, derivation, value);
8284
8460
  }
8285
- } else translateVar(tag, value);
8461
+ } else if (!varBinding?.pruned || !value.extra?.pruned) translateVar(tag, value);
8286
8462
  tag.remove();
8287
8463
  } },
8288
8464
  parseOptions: { openTagOnly: true },
@@ -8489,7 +8665,7 @@ var html_comment_default = {
8489
8665
  const tagExtra = mergeReferences(tagSection, tag.node, referenceNodes);
8490
8666
  nodeBinding = tagExtra[kNodeBinding$1] = createBinding("#comment", 0, tagSection, void 0, void 0, void 0, void 0, !!tagVar);
8491
8667
  trackDomVarReferences(tag, nodeBinding);
8492
- if (tagVar) addSerializeExpr(tagSection, true, nodeBinding);
8668
+ if (tagVar) addSerializeReason(tagSection, FORCED, nodeBinding);
8493
8669
  addSerializeExpr(tagSection, tagExtra, nodeBinding);
8494
8670
  }
8495
8671
  const write = writeTo(tag);
@@ -8672,14 +8848,24 @@ var let_default = {
8672
8848
  const tagSection = getOrCreateSection(tag);
8673
8849
  const binding = trackVarReferences(tag, 1);
8674
8850
  const tagExtra = mergeReferences(tagSection, tag.node, [valueAttr?.value, valueChangeAttr?.value]);
8851
+ setBindingDownstream(binding, tagExtra);
8675
8852
  if (valueChangeAttr) {
8676
8853
  binding.reserveSize = 1;
8677
- setBindingDownstream(binding, tagExtra);
8678
- if (binding.assignmentSections) addSerializeReason(tagSection, true, binding, getAccessorPrefix().TagVariableChange);
8679
- } else setBindingDownstream(binding, false);
8854
+ tagExtra.forceRegister = true;
8855
+ onFinalizeReferences(() => {
8856
+ if (binding.assignments) addSerializeReason(tagSection, FORCED, binding, getAccessorPrefix().TagVariableChange);
8857
+ });
8858
+ } else {
8859
+ tagExtra.initialValue = true;
8860
+ tagExtra.pure = !valueAttr || evaluate(valueAttr.value).pure;
8861
+ }
8680
8862
  },
8681
8863
  translate: { exit(tag) {
8682
8864
  const { node } = tag;
8865
+ if (node.extra?.pruned) {
8866
+ tag.remove();
8867
+ return;
8868
+ }
8683
8869
  const tagVar = node.var;
8684
8870
  const valueAttr = node.attributes.find((attr) => _marko_compiler.types.isMarkoAttribute(attr) && (attr.default || attr.name === "value")) ?? _marko_compiler.types.markoAttribute("value", _marko_compiler.types.identifier("undefined"));
8685
8871
  const valueChangeAttr = node.attributes.find((attr) => _marko_compiler.types.isMarkoAttribute(attr) && attr.name === "valueChange");
@@ -9170,6 +9356,7 @@ var style_default = {
9170
9356
  analyzeDynamicStyle(tag, names);
9171
9357
  addSetupStatement(getOrCreateSection(tag));
9172
9358
  visit(tag, 32);
9359
+ enterShallow(tag);
9173
9360
  writeTo(tag)`<style></style>`;
9174
9361
  }
9175
9362
  },
@@ -9339,7 +9526,6 @@ function getStyleImportPath(file, node, names) {
9339
9526
  }
9340
9527
  //#endregion
9341
9528
  //#region src/translator/core/try.ts
9342
- const kDOMBinding$1 = Symbol("try tag dom binding");
9343
9529
  var try_default = {
9344
9530
  analyze(tag) {
9345
9531
  (0, _marko_compiler_babel_utils.assertNoVar)(tag);
@@ -9355,7 +9541,7 @@ var try_default = {
9355
9541
  }
9356
9542
  const section = getOrCreateSection(tag);
9357
9543
  const tagExtra = mergeReferences(section, tag.node, getAllTagReferenceNodes(tag.node));
9358
- tagExtra[kDOMBinding$1] = createBinding("#text", 0, section);
9544
+ tagExtra.nodeBinding = createBinding("#text", 0, section);
9359
9545
  if (!tag.node.body.body.length) throw tag.get("name").buildCodeFrameError("The [`<try>` tag](https://markojs.com/docs/reference/core-tag#try) requires [body content](https://markojs.com/docs/reference/language#tag-content).");
9360
9546
  const bodySection = startSection(tag.get("body"));
9361
9547
  if (bodySection) {
@@ -9382,7 +9568,7 @@ var try_default = {
9382
9568
  const tagExtra = node.extra;
9383
9569
  const tagBody = tag.get("body");
9384
9570
  const translatedAttrs = translateAttrs(tag);
9385
- const nodeRef = tagExtra[kDOMBinding$1];
9571
+ const nodeRef = tagExtra.nodeBinding;
9386
9572
  const contentProp = getTranslatedBodyContentProperty(translatedAttrs.properties);
9387
9573
  if (contentProp) translatedAttrs.properties.splice(translatedAttrs.properties.indexOf(contentProp), 1);
9388
9574
  flushInto(tag);
@@ -9400,7 +9586,7 @@ var try_default = {
9400
9586
  exit(tag) {
9401
9587
  const { node } = tag;
9402
9588
  const tagExtra = node.extra;
9403
- const nodeRef = tagExtra[kDOMBinding$1];
9589
+ const nodeRef = tagExtra.nodeBinding;
9404
9590
  const referencedBindings = tagExtra.referencedBindings;
9405
9591
  const translatedAttrs = translateAttrs(tag);
9406
9592
  const contentProp = getTranslatedBodyContentProperty(translatedAttrs.properties);
@@ -9849,8 +10035,8 @@ var referenced_identifier_default = {
9849
10035
  const section = getOrCreateSection(identifier);
9850
10036
  section.hasAbortSignal = true;
9851
10037
  setReferencesScope(identifier);
9852
- const exprRoot = getExprRoot(identifier);
9853
- const rootExtra = exprRoot.node.extra ??= { section };
10038
+ const rootExtra = getExprRoot(identifier).node.extra ??= { section };
10039
+ (identifier.node.extra ??= {}).exprRoot = rootExtra;
9854
10040
  if (rootExtra.abortId === void 0) rootExtra.abortId = section.abortSignalExprs++;
9855
10041
  }
9856
10042
  },
@@ -9869,12 +10055,12 @@ var referenced_identifier_default = {
9869
10055
  case "$signal": if (isOutputHTML()) identifier.replaceWith(_marko_compiler.types.callExpression(_marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([_marko_compiler.types.throwStatement(_marko_compiler.types.newExpression(_marko_compiler.types.identifier("Error"), [_marko_compiler.types.stringLiteral("Cannot use $signal in a server render.")]))])), []));
9870
10056
  else {
9871
10057
  const section = getSection(identifier);
9872
- const exprRoot = getExprRoot(identifier);
9873
- const exprId = exprRoot.node.extra.abortId;
10058
+ const exprRoot = identifier.node.extra.exprRoot;
10059
+ const exprId = exprRoot.abortId;
9874
10060
  const resetEmitted = getAbortResetEmitted(section);
9875
10061
  if (!resetEmitted.has(exprRoot)) {
9876
10062
  resetEmitted.add(exprRoot);
9877
- addStatement("render", section, exprRoot.node.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(importRuntime("$signalReset"), [scopeIdentifier, _marko_compiler.types.numericLiteral(exprId)])));
10063
+ addStatement("render", section, exprRoot.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(importRuntime("$signalReset"), [scopeIdentifier, _marko_compiler.types.numericLiteral(exprId)])));
9878
10064
  }
9879
10065
  identifier.replaceWith(_marko_compiler.types.callExpression(importRuntime("$signal"), [scopeIdentifier, _marko_compiler.types.numericLiteral(exprId)]));
9880
10066
  }
@@ -9960,6 +10146,7 @@ var custom_tag_default = {
9960
10146
  const programSection = programExtra.section;
9961
10147
  const childExtra = childFile.ast.program.extra;
9962
10148
  const childSection = childExtra.section;
10149
+ 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>\`.`);
9963
10150
  if (childExtra.page) programExtra.page ??= true;
9964
10151
  if (tagExtra.tagNameLoad) tagExtra[kLoadTagBinding] = createBinding("#text", 0, getOrCreateSection(tag));
9965
10152
  if (tagExtra.tagNameLoad || !childExtra.domExports?.setupEmpty) addSetupStatement(getOrCreateSection(tag));
@@ -10082,10 +10269,7 @@ function tagNotFoundError(tag) {
10082
10269
  const proseText = tagName && getProseText(tag);
10083
10270
  if (knownWrongTagHint) didYouMean = ` ${knownWrongTagHint}`;
10084
10271
  else if (proseText) didYouMean = ` If this line is meant to be text, prefix it with \`--\` (e.g. \`-- ${proseText}\`) or wrap it in an element such as \`<p>${proseText}</p>\`.`;
10085
- else if (tagName) {
10086
- const closestTag = (0, fastest_levenshtein.closest)(tagName, Object.keys((0, _marko_compiler_babel_utils.getTaglibLookup)((0, _marko_compiler_babel_utils.getFile)()).merged.tags));
10087
- if ((0, fastest_levenshtein.distance)(tagName, closestTag) < 4) didYouMean = ` Did you mean \`<${closestTag}>\`?`;
10088
- }
10272
+ else if (tagName) didYouMean = getSimilarTagHint(tagName);
10089
10273
  return tag.get("name").buildCodeFrameError(`Unable to find entry point for [custom tag](https://markojs.com/docs/reference/custom-tag#relative-custom-tags) \`<${tagName ?? getStaticTagName(tag.node)}>\`.${didYouMean}`);
10090
10274
  }
10091
10275
  const wordReg = /^[A-Za-z]+$/;
@@ -10109,6 +10293,25 @@ function collectProseWords(node, tagName) {
10109
10293
  }
10110
10294
  return text;
10111
10295
  }
10296
+ function getSimilarTagHint(tagName) {
10297
+ const lookup = (0, _marko_compiler_babel_utils.getTaglibLookup)((0, _marko_compiler_babel_utils.getFile)());
10298
+ if (lookup.getTag(tagName)) return "";
10299
+ const lowerTagName = tagName.toLowerCase();
10300
+ let closestTag;
10301
+ let closestDistance = 4;
10302
+ for (const name in lookup.merged.tags) {
10303
+ const lengthDelta = Math.abs(name.length - tagName.length);
10304
+ if (lengthDelta < closestDistance) {
10305
+ if (!lengthDelta && name.toLowerCase() === lowerTagName) return ` Tag names are case-sensitive: did you mean \`<${name}>\`?`;
10306
+ const nameDistance = (0, fastest_levenshtein.distance)(tagName, name);
10307
+ if (nameDistance < closestDistance) {
10308
+ closestTag = name;
10309
+ closestDistance = nameDistance;
10310
+ }
10311
+ }
10312
+ }
10313
+ return closestTag ? ` Did you mean \`<${closestTag}>\`?` : "";
10314
+ }
10112
10315
  function buildLoadSetupVirtualModule(file, childFileName, childExports) {
10113
10316
  const parts = `${childExports.template}, ${childExports.walks}, ${childExports.setup}`;
10114
10317
  return getMarkoOpts().resolveVirtualDependency(file.opts.filename, {
@@ -10140,10 +10343,8 @@ function optionalValueToNode(value) {
10140
10343
  }
10141
10344
  //#endregion
10142
10345
  //#region src/translator/visitors/tag/dynamic-tag.ts
10143
- const kDOMBinding = Symbol("dynamic tag dom binding");
10144
10346
  const kChildOffsetScopeBinding = Symbol("custom tag scope offset");
10145
- const importedDynamicTagResume = /* @__PURE__ */ new WeakSet();
10146
- const importedDynamicTagVarResume = /* @__PURE__ */ new WeakSet();
10347
+ const [getAddedRuntime] = createProgramState(() => /* @__PURE__ */ new Set());
10147
10348
  const [getCompatRegistrations] = createProgramState(() => /* @__PURE__ */ new Set());
10148
10349
  const [getCompatBoundaryCalls] = createProgramState(() => /* @__PURE__ */ new Map());
10149
10350
  function pushCompatRegistration(key, statement) {
@@ -10172,18 +10373,23 @@ var dynamic_tag_default = {
10172
10373
  const tagSection = getOrCreateSection(tag);
10173
10374
  const inputNodes = getAllTagReferenceNodes(node);
10174
10375
  const tagExtra = mergeReferences(tagSection, node, [node.name, ...inputNodes]);
10175
- if (inputNodes.length) tagExtra.dynamicTagInput = true;
10376
+ if (inputNodes.length) tagExtra.forceRegister = true;
10176
10377
  const tagBody = tag.get("body");
10177
10378
  const hasVar = !!tag.node.var;
10178
- const nodeBinding = tagExtra[kDOMBinding] = createBinding("#text", 0, tagSection);
10179
- if (hasVar || tag.node.attributes.some((attr) => _marko_compiler.types.isMarkoSpreadAttribute(attr) || isEventOrChangeHandler(attr.name))) (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
10379
+ const usesVar = hasVar && isTagVarUsed(tag);
10380
+ const nodeBinding = tagExtra.nodeBinding = createBinding("#text", 0, tagSection);
10381
+ if (usesVar || tag.node.attributes.some((attr) => _marko_compiler.types.isMarkoSpreadAttribute(attr) || isEventOrChangeHandler(attr.name))) (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
10180
10382
  if (hasVar) {
10181
10383
  trackVarReferences(tag, 5);
10182
10384
  tag.node.var.extra.binding.scopeOffset = tagExtra[kChildOffsetScopeBinding] = createBinding("#scopeOffset", 0, tagSection);
10183
10385
  }
10184
10386
  const bodySection = startSection(tagBody);
10387
+ if (bodySection) {
10388
+ bodySection.upstreamExpression = tagExtra;
10389
+ if (analyzeTagNameType(tag, true) === 1 && !node.arguments) setTagDownstream(tag, getDynamicTagInputBindings(tagExtra), { value: tagExtra });
10390
+ }
10185
10391
  trackParamsReferences(tagBody, 3);
10186
- if (hasVar) addSerializeExpr(tagSection, true, nodeBinding);
10392
+ if (usesVar) addSerializeReason(tagSection, FORCED, nodeBinding);
10187
10393
  addSerializeExpr(tagSection, tagExtra, nodeBinding);
10188
10394
  if (!hasVar && !node.arguments && !node.attributes.length && !node.body.body.length) tagExtra[kDirectContent] = true;
10189
10395
  if (tagExtra.featureType !== "class" || (0, _marko_compiler_babel_utils.getTagTemplate)(tag)) {
@@ -10218,7 +10424,7 @@ var dynamic_tag_default = {
10218
10424
  return;
10219
10425
  }
10220
10426
  const tagExtra = node.extra;
10221
- const nodeBinding = tagExtra[kDOMBinding];
10427
+ const nodeBinding = tagExtra.nodeBinding;
10222
10428
  const isClassAPI = tagExtra.featureType === "class";
10223
10429
  const tagsSerializeReason = getSerializeReason(tagSection, nodeBinding);
10224
10430
  const serializeReason = tagsSerializeReason;
@@ -10242,7 +10448,7 @@ var dynamic_tag_default = {
10242
10448
  ...preserveBoundary ? [_marko_compiler.types.stringLiteral("preserve")] : []
10243
10449
  ]) : void 0;
10244
10450
  if (isOutputHTML() ? serializeReason || classHydration : serializeReason) {
10245
- if (pushCompatRegistration(classId, registration ? _marko_compiler.types.markoScriptlet([_marko_compiler.types.expressionStatement(registration)], true) : _marko_compiler.types.expressionStatement(callRuntime("_resume", _marko_compiler.types.stringLiteral(classId), _marko_compiler.types.identifier(tagExpression.name)))) && registration) getCompatBoundaryCalls().set(classId, registration);
10451
+ if (pushCompatRegistration(classId, registration ? _marko_compiler.types.markoScriptlet([_marko_compiler.types.expressionStatement(registration)], true) : _marko_compiler.types.expressionStatement(registerRuntimeValue(classId, _marko_compiler.types.identifier(tagExpression.name)))) && registration) getCompatBoundaryCalls().set(classId, registration);
10246
10452
  }
10247
10453
  if (!preserveBoundary) {
10248
10454
  const emitted = getCompatBoundaryCalls().get(classId);
@@ -10270,12 +10476,13 @@ var dynamic_tag_default = {
10270
10476
  writeHTMLResumeStatements(tag.get("body"));
10271
10477
  const serializeArg = getSerializeGuard(tagSection, serializeReason, true);
10272
10478
  const dynamicTagExpr = hasTagArgs ? callRuntime("_dynamic_tag", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), tagExpression, _marko_compiler.types.arrayExpression(args), contentProp ? contentProp.value : _marko_compiler.types.numericLiteral(0), _marko_compiler.types.numericLiteral(1), serializeArg) : callRuntime("_dynamic_tag", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), tagExpression, args[0], args[1] || (serializeArg ? _marko_compiler.types.numericLiteral(0) : void 0), serializeArg ? _marko_compiler.types.numericLiteral(0) : void 0, serializeArg);
10273
- if (node.var) {
10479
+ if (node.var && isTagVarResumed(tag)) {
10274
10480
  const dynamicScopeIdentifier = generateUidIdentifier(tag.get("name").toString() + "_scope");
10275
- const mutatesTagVar = !!(tag.node.var.type === "Identifier" && tag.scope.getBinding(tag.node.var.name)?.constantViolations.length);
10481
+ const mutatesTagVar = isTagVarAssigned(tag);
10276
10482
  statements.push(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(dynamicScopeIdentifier, callRuntime("_peek_scope_id"))]));
10277
10483
  statements.push(_marko_compiler.types.variableDeclaration("let", [_marko_compiler.types.variableDeclarator(node.var, dynamicTagExpr)]), _marko_compiler.types.expressionStatement(callRuntime("_var", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(tag.node.extra[kChildOffsetScopeBinding]), dynamicScopeIdentifier, _marko_compiler.types.stringLiteral(getResumeRegisterId(tagSection, node.var.extra?.binding, "var")), mutatesTagVar ? getScopeAccessorLiteral(nodeBinding) : void 0)));
10278
- } else statements.push(_marko_compiler.types.expressionStatement(dynamicTagExpr));
10484
+ } else if (node.var) statements.push(_marko_compiler.types.variableDeclaration("let", [_marko_compiler.types.variableDeclarator(node.var, dynamicTagExpr)]));
10485
+ else statements.push(_marko_compiler.types.expressionStatement(dynamicTagExpr));
10279
10486
  for (const replacement of tag.replaceWithMultiple(statements)) replacement.skip();
10280
10487
  } else {
10281
10488
  const section = getSection(tag);
@@ -10285,7 +10492,8 @@ var dynamic_tag_default = {
10285
10492
  if (tag.node.var) {
10286
10493
  const varBinding = tag.node.var.extra.binding;
10287
10494
  tagVarSignal = initValue(varBinding);
10288
- tagVarSignal.register = tagVarSignal.referenced = true;
10495
+ tagVarSignal.register = isTagVarResumed(tag);
10496
+ tagVarSignal.referenced = true;
10289
10497
  tagVarSignal.buildAssignment = (valueSection, value) => {
10290
10498
  const changeArgs = [_marko_compiler.types.memberExpression(getScopeExpression(tagVarSignal.section, valueSection), _marko_compiler.types.stringLiteral(getAccessorPrefix().BranchScopes + getScopeAccessor(nodeBinding)), true), value];
10291
10499
  if (!isOptimize()) changeArgs.push(_marko_compiler.types.stringLiteral(varBinding.name));
@@ -10303,7 +10511,7 @@ var dynamic_tag_default = {
10303
10511
  }
10304
10512
  if (!isClassAPI) {
10305
10513
  enableDynamicTagResume(tag);
10306
- enableDynamicTagVarResume(tag);
10514
+ enableDynamicTagVar(tag);
10307
10515
  enableDynamicTagControllables(tag);
10308
10516
  }
10309
10517
  addValue(section, tagExtra.referencedBindings, signal, tagExpression);
@@ -10321,22 +10529,46 @@ function enableDynamicTagControllables(tag) {
10321
10529
  return;
10322
10530
  }
10323
10531
  }
10324
- function enableDynamicTagVarResume(tag) {
10325
- const program = (0, _marko_compiler_babel_utils.getProgram)().node;
10326
- if (tag.node.var && !importedDynamicTagVarResume.has(program) && analyzeTagNameType(tag, true) !== 1) {
10327
- importedDynamicTagVarResume.add(program);
10328
- importRuntimeFeature("dynamic-tag-var");
10532
+ function enableDynamicTagVar(tag) {
10533
+ if (!tag.node.var || !isTagVarResumed(tag) || analyzeTagNameType(tag, true) === 1) return;
10534
+ importRuntimeFeature("dynamic-tag-var");
10535
+ if (!tag.node.var.extra.binding.pruned) {
10536
+ const accessor = getScopeAccessorLiteral(tag.node.extra.nodeBinding, true);
10537
+ if (addRuntimeOnce(`_resume_dynamic_tag_var ${accessor.value}`)) (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.expressionStatement(callRuntime("_resume_dynamic_tag_var", accessor)));
10329
10538
  }
10330
10539
  }
10331
10540
  function enableDynamicTagResume(tag) {
10332
- const program = (0, _marko_compiler_babel_utils.getProgram)().node;
10333
- if (!importedDynamicTagResume.has(program) && analyzeTagNameType(tag, true) !== 1) {
10334
- for (const attr of tag.node.attributes) if (attr.type === "MarkoSpreadAttribute" || attr.type === "MarkoAttribute" && isEventOrChangeHandler(attr.name)) {
10335
- importedDynamicTagResume.add(program);
10336
- program.body.push(_marko_compiler.types.expressionStatement(callRuntime("_resume_dynamic_tag")));
10337
- return;
10338
- }
10541
+ if (analyzeTagNameType(tag, true) === 1) return;
10542
+ for (const attr of tag.node.attributes) if (attr.type === "MarkoSpreadAttribute" || attr.type === "MarkoAttribute" && isEventOrChangeHandler(attr.name)) {
10543
+ importRuntimeFeature("dynamic-tag-script");
10544
+ return;
10545
+ }
10546
+ }
10547
+ function addRuntimeOnce(key) {
10548
+ const added = getAddedRuntime();
10549
+ return !added.has(key) && !!added.add(key);
10550
+ }
10551
+ function getDynamicTagInputBindings(tagExtra) {
10552
+ let inputBindings;
10553
+ for (const childExtra of tagExtra.tagNameTemplates || []) {
10554
+ if (childExtra.featureType === "class") return;
10555
+ const inputBinding = childExtra.domExports?.params?.props?.[0]?.binding;
10556
+ if (inputBinding) inputBindings = bindingUtil.add(inputBindings, inputBinding);
10339
10557
  }
10558
+ return inputBindings;
10559
+ }
10560
+ function isTagVarUsed(tag) {
10561
+ for (const name in _marko_compiler.types.getBindingIdentifiers(tag.node.var)) {
10562
+ const binding = tag.scope.getBinding(name);
10563
+ if (binding?.referencePaths.length || binding?.constantViolations.length) return true;
10564
+ }
10565
+ return false;
10566
+ }
10567
+ function isTagVarResumed(tag) {
10568
+ return !tag.node.var.extra.binding.pruned || isTagVarAssigned(tag);
10569
+ }
10570
+ function isTagVarAssigned(tag) {
10571
+ return !!(tag.node.var.type === "Identifier" && tag.scope.getBinding(tag.node.var.name)?.constantViolations.length);
10340
10572
  }
10341
10573
  //#endregion
10342
10574
  //#region src/translator/visitors/tag/index.ts
@@ -10818,7 +11050,9 @@ const taglibs = [[core_default.taglibId, {
10818
11050
  migrate: visitors.migrate
10819
11051
  }]];
10820
11052
  function getRuntimeEntryFiles(output, optimize) {
10821
- return [`${runtime_info_default.name}${optimize ? "" : "/debug"}/${output === "html" ? "html" : "dom"}`];
11053
+ const runtime = `${runtime_info_default.name}${optimize ? "" : "/debug"}`;
11054
+ if (output === "html") return [`${runtime}/html`];
11055
+ return [`${runtime}/dom`, ...domRuntimeFeatures.map((feature) => `${runtime}/dom/${feature}.feat`)];
10822
11056
  }
10823
11057
  //#endregion
10824
11058
  exports.analyze = analyze;