marko 6.4.4 → 6.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -700,19 +700,18 @@ function writeScopesRoot(state, flushes) {
700
700
  const ref = state.refs.get(scope) || newScopeReference(state, scope, scopeId);
701
701
  const openIndex = buf.push("") - 1;
702
702
  if (writeObjectProps(state, flush[2], ref)) {
703
- buf[openIndex] = nextSlotId === -1 ? "[" + scopeId + ",{" : (scopeId !== nextSlotId ? "," + (scopeId - nextSlotId) : "") + ",{";
703
+ buf[openIndex] = nextSlotId === -1 ? scopeId + ",{" : (scopeId !== nextSlotId ? "," + (scopeId - nextSlotId) : "") + ",{";
704
704
  if (fillIndex === -1) fillIndex = openIndex;
705
705
  nextSlotId = scopeId + 1;
706
706
  buf.push("}");
707
707
  } else buf.pop();
708
708
  }
709
- if (nextSlotId !== -1) buf.push("]");
710
709
  let extras = "";
711
710
  if (state.pendingAssignments.size || hasChannelMutations(state)) {
712
711
  extras = ",0)";
713
712
  if (fillIndex !== -1) {
714
- buf[fillIndex] = "_(" + buf[fillIndex];
715
- buf.push(")");
713
+ buf[fillIndex] = "_([" + buf[fillIndex];
714
+ buf.push("])");
716
715
  }
717
716
  writeAssigned(state);
718
717
  }
@@ -720,10 +719,9 @@ function writeScopesRoot(state, flushes) {
720
719
  for (const chunk of buf) result += chunk;
721
720
  result += extras;
722
721
  if (!result) return "";
723
- if (state.wroteUndefined) {
724
- state.wroteUndefined = false;
725
- return "(_,$)=>" + result;
726
- } else return "_=>" + result;
722
+ const arrow = state.wroteUndefined ? "(_,$)=>" : "_=>";
723
+ state.wroteUndefined = false;
724
+ return extras ? arrow + result : arrow + "[" + result + "]";
727
725
  }
728
726
  function writeAssigned(state) {
729
727
  let sep = state.buf.length ? "," : "";
@@ -698,19 +698,18 @@ function writeScopesRoot(state, flushes) {
698
698
  const ref = state.refs.get(scope) || newScopeReference(state, scope, scopeId);
699
699
  const openIndex = buf.push("") - 1;
700
700
  if (writeObjectProps(state, flush[2], ref)) {
701
- buf[openIndex] = nextSlotId === -1 ? "[" + scopeId + ",{" : (scopeId !== nextSlotId ? "," + (scopeId - nextSlotId) : "") + ",{";
701
+ buf[openIndex] = nextSlotId === -1 ? scopeId + ",{" : (scopeId !== nextSlotId ? "," + (scopeId - nextSlotId) : "") + ",{";
702
702
  if (fillIndex === -1) fillIndex = openIndex;
703
703
  nextSlotId = scopeId + 1;
704
704
  buf.push("}");
705
705
  } else buf.pop();
706
706
  }
707
- if (nextSlotId !== -1) buf.push("]");
708
707
  let extras = "";
709
708
  if (state.pendingAssignments.size || hasChannelMutations(state)) {
710
709
  extras = ",0)";
711
710
  if (fillIndex !== -1) {
712
- buf[fillIndex] = "_(" + buf[fillIndex];
713
- buf.push(")");
711
+ buf[fillIndex] = "_([" + buf[fillIndex];
712
+ buf.push("])");
714
713
  }
715
714
  writeAssigned(state);
716
715
  }
@@ -718,10 +717,9 @@ function writeScopesRoot(state, flushes) {
718
717
  for (const chunk of buf) result += chunk;
719
718
  result += extras;
720
719
  if (!result) return "";
721
- if (state.wroteUndefined) {
722
- state.wroteUndefined = false;
723
- return "(_,$)=>" + result;
724
- } else return "_=>" + result;
720
+ const arrow = state.wroteUndefined ? "(_,$)=>" : "_=>";
721
+ state.wroteUndefined = false;
722
+ return extras ? arrow + result : arrow + "[" + result + "]";
725
723
  }
726
724
  function writeAssigned(state) {
727
725
  let sep = state.buf.length ? "," : "";
package/dist/html.js CHANGED
@@ -615,14 +615,15 @@ function writeScopesRoot(state, flushes) {
615
615
  let { buf } = state, nextSlotId = -1, fillIndex = -1;
616
616
  for (let flush of flushes) {
617
617
  let scopeId = flush[0], scope = flush[1], ref = state.refs.get(scope) || newScopeReference(state, scope, scopeId), openIndex = buf.push("") - 1;
618
- writeObjectProps(state, flush[2], ref) ? (buf[openIndex] = nextSlotId === -1 ? "[" + scopeId + ",{" : (scopeId === nextSlotId ? "" : "," + (scopeId - nextSlotId)) + ",{", fillIndex === -1 && (fillIndex = openIndex), nextSlotId = scopeId + 1, buf.push("}")) : buf.pop();
618
+ writeObjectProps(state, flush[2], ref) ? (buf[openIndex] = nextSlotId === -1 ? scopeId + ",{" : (scopeId === nextSlotId ? "" : "," + (scopeId - nextSlotId)) + ",{", fillIndex === -1 && (fillIndex = openIndex), nextSlotId = scopeId + 1, buf.push("}")) : buf.pop();
619
619
  }
620
- nextSlotId !== -1 && buf.push("]");
621
620
  let extras = "";
622
- (state.pendingAssignments.size || hasChannelMutations(state)) && (extras = ",0)", fillIndex !== -1 && (buf[fillIndex] = "_(" + buf[fillIndex], buf.push(")")), writeAssigned(state));
621
+ (state.pendingAssignments.size || hasChannelMutations(state)) && (extras = ",0)", fillIndex !== -1 && (buf[fillIndex] = "_([" + buf[fillIndex], buf.push("])")), writeAssigned(state));
623
622
  let result = extras && "(";
624
623
  for (let chunk of buf) result += chunk;
625
- return result += extras, result ? state.wroteUndefined ? (state.wroteUndefined = !1, "(_,$)=>" + result) : "_=>" + result : "";
624
+ if (result += extras, !result) return "";
625
+ let arrow = state.wroteUndefined ? "(_,$)=>" : "_=>";
626
+ return state.wroteUndefined = !1, extras ? arrow + result : arrow + "[" + result + "]";
626
627
  }
627
628
  function writeAssigned(state) {
628
629
  let sep = state.buf.length ? "," : "";
package/dist/html.mjs CHANGED
@@ -613,14 +613,15 @@ function writeScopesRoot(state, flushes) {
613
613
  let { buf } = state, nextSlotId = -1, fillIndex = -1;
614
614
  for (let flush of flushes) {
615
615
  let scopeId = flush[0], scope = flush[1], ref = state.refs.get(scope) || newScopeReference(state, scope, scopeId), openIndex = buf.push("") - 1;
616
- writeObjectProps(state, flush[2], ref) ? (buf[openIndex] = nextSlotId === -1 ? "[" + scopeId + ",{" : (scopeId === nextSlotId ? "" : "," + (scopeId - nextSlotId)) + ",{", fillIndex === -1 && (fillIndex = openIndex), nextSlotId = scopeId + 1, buf.push("}")) : buf.pop();
616
+ writeObjectProps(state, flush[2], ref) ? (buf[openIndex] = nextSlotId === -1 ? scopeId + ",{" : (scopeId === nextSlotId ? "" : "," + (scopeId - nextSlotId)) + ",{", fillIndex === -1 && (fillIndex = openIndex), nextSlotId = scopeId + 1, buf.push("}")) : buf.pop();
617
617
  }
618
- nextSlotId !== -1 && buf.push("]");
619
618
  let extras = "";
620
- (state.pendingAssignments.size || hasChannelMutations(state)) && (extras = ",0)", fillIndex !== -1 && (buf[fillIndex] = "_(" + buf[fillIndex], buf.push(")")), writeAssigned(state));
619
+ (state.pendingAssignments.size || hasChannelMutations(state)) && (extras = ",0)", fillIndex !== -1 && (buf[fillIndex] = "_([" + buf[fillIndex], buf.push("])")), writeAssigned(state));
621
620
  let result = extras && "(";
622
621
  for (let chunk of buf) result += chunk;
623
- return result += extras, result ? state.wroteUndefined ? (state.wroteUndefined = !1, "(_,$)=>" + result) : "_=>" + result : "";
622
+ if (result += extras, !result) return "";
623
+ let arrow = state.wroteUndefined ? "(_,$)=>" : "_=>";
624
+ return state.wroteUndefined = !1, extras ? arrow + result : arrow + "[" + result + "]";
624
625
  }
625
626
  function writeAssigned(state) {
626
627
  let sep = state.buf.length ? "," : "";
@@ -1834,12 +1834,12 @@ const builder = {
1834
1834
  }
1835
1835
  return body;
1836
1836
  },
1837
- visit(file, entryFile, visitChild = (id, bundled = false) => {
1837
+ visit(file, entryFile, visitChild = (id, reach = 0) => {
1838
1838
  const state = entryFile[kState];
1839
1839
  const resolved = resolveRelativeToEntry(entryFile, file, id);
1840
- const seenBundled = state.visited.get(resolved);
1841
- if (seenBundled === false || seenBundled && bundled) return;
1842
- state.visited.set(resolved, bundled);
1840
+ const seen = state.visited.get(resolved);
1841
+ if (seen !== void 0 && seen <= reach) return;
1842
+ state.visited.set(resolved, reach);
1843
1843
  const childFile = (0, _marko_compiler_babel_utils.loadFileForImport)(entryFile, resolved);
1844
1844
  if (childFile) builder.visit(childFile, entryFile);
1845
1845
  }) {
@@ -1848,10 +1848,11 @@ const builder = {
1848
1848
  load: false,
1849
1849
  lazy: false,
1850
1850
  bundled: 0,
1851
+ lazyDepth: 0,
1851
1852
  roots: [],
1852
1853
  assets: /* @__PURE__ */ new Set(),
1853
1854
  bundledAssets: /* @__PURE__ */ new Set(),
1854
- visited: /* @__PURE__ */ new Map([[(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, entryFile.opts.filename), false]])
1855
+ visited: /* @__PURE__ */ new Map([[(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, entryFile.opts.filename), 0]])
1855
1856
  };
1856
1857
  const programExtra = file.path.node.extra;
1857
1858
  const { analyzedTags, assetImports } = file.metadata.marko;
@@ -1863,16 +1864,22 @@ const builder = {
1863
1864
  if (load) state.load = true;
1864
1865
  if (loadImports) state.lazy = true;
1865
1866
  if (isRoot) state.roots.push((0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, file.opts.filename));
1866
- if (assetImports) {
1867
+ if (assetImports && !state.lazyDepth) {
1867
1868
  const assets = isRoot || state.bundled ? state.bundledAssets : state.assets;
1868
1869
  for (const request of assetImports) assets.add(resolveRelativeToEntry(entryFile, file, request));
1869
1870
  }
1870
1871
  if (isRoot) state.bundled++;
1871
1872
  for (const tag of analyzedTags ? [...analyzedTags] : []) {
1872
1873
  const lazy = loadImports?.has(tag);
1873
- if (lazy) state.bundled++;
1874
- visitChild(tag, !!state.bundled);
1875
- if (lazy) state.bundled--;
1874
+ if (lazy) {
1875
+ state.bundled++;
1876
+ state.lazyDepth++;
1877
+ }
1878
+ visitChild(tag, state.lazyDepth ? 2 : state.bundled ? 1 : 0);
1879
+ if (lazy) {
1880
+ state.bundled--;
1881
+ state.lazyDepth--;
1882
+ }
1876
1883
  }
1877
1884
  if (isRoot) state.bundled--;
1878
1885
  }
@@ -2758,6 +2765,12 @@ function buildGroupMask(groups) {
2758
2765
  function getScopeReasonStatement(section) {
2759
2766
  return hasConditionalReason(section) ? _marko_compiler.types.variableDeclaration("const", getSectionGuards(section).declarators) : _marko_compiler.types.expressionStatement(callRuntime("_scope_reason"));
2760
2767
  }
2768
+ function getWriteReason(binding) {
2769
+ return findSlot(binding)?.reason;
2770
+ }
2771
+ function getBranchWriteReason(section) {
2772
+ return findSectionSlot(section, 9)?.reason;
2773
+ }
2761
2774
  function getWriteGuard(section, reason, optional) {
2762
2775
  if (!isDynamicWriteGuard(section, reason)) {
2763
2776
  if (!reason) return _marko_compiler.types.numericLiteral(0);
@@ -3242,8 +3255,12 @@ function getDestructurePattern(id) {
3242
3255
  //#region src/translator/util/signals.ts
3243
3256
  const [getSignals] = createSectionState("signals", () => /* @__PURE__ */ new Map());
3244
3257
  const [getClosureSignalBuilder, _setClosureSignalBuilder] = createSectionState("queue");
3245
- function setClosureSignalBuilder(tag, builder) {
3246
- _setClosureSignalBuilder(getSectionForBody(tag.get("body")), builder);
3258
+ function setClosureSignalBuilder(tag, hop, build = (_closure, render) => buildClosureHop(hop, render)) {
3259
+ _setClosureSignalBuilder(getSectionForBody(tag.get("body")), build);
3260
+ }
3261
+ function buildClosureHop(hop, render) {
3262
+ const accessor = getScopeAccessorLiteral(hop.ref, true);
3263
+ return hop.kind === "if" ? callRuntime("_if_closure", accessor, _marko_compiler.types.numericLiteral(hop.index), render) : callRuntime("_for_closure", accessor, render);
3247
3264
  }
3248
3265
  const [getOwnerResumedByMarker, setOwnerResumedByMarker] = createSectionState("ownerResumedByMarker");
3249
3266
  function setSectionOwnerResumedByMarker(section) {
@@ -3704,7 +3721,10 @@ function writeHTMLResumeStatements(path) {
3704
3721
  const closureScopesReason = findSlot(closure, 2)?.reason;
3705
3722
  const subscribeArg = isConditionalReason(closureScopesReason) && !isSameReason(closureScopesReason, sectionReason) ? getExprIfWritten(closure.section, closureScopesReason, identifier) : identifier;
3706
3723
  const changeable = isChangeableDynamicClosure(section, closure);
3707
- addWriteScopeBuilder(section, (expr) => callRuntime("_subscribe", subscribeArg, expr, changeable ? _marko_compiler.types.stringLiteral(getResumeRegisterId(section, closure, "subscribe")) : void 0, changeable ? markerGuard : void 0));
3724
+ addWriteScopeBuilder(section, (expr) => {
3725
+ const resumeId = changeable && _marko_compiler.types.stringLiteral(getResumeRegisterId(section, closure, "subscribe"));
3726
+ return callRuntime("_subscribe", subscribeArg, expr, resumeId, resumeId && markerGuard);
3727
+ });
3708
3728
  }
3709
3729
  }
3710
3730
  });
@@ -3722,7 +3742,7 @@ function writeHTMLResumeStatements(path) {
3722
3742
  };
3723
3743
  let debugVars;
3724
3744
  const writeBinding = (binding) => {
3725
- const reason = findSlot(binding)?.reason;
3745
+ const reason = getWriteReason(binding);
3726
3746
  if (!reason) return;
3727
3747
  const accessor = getScopeAccessor(binding);
3728
3748
  pendingProperties.delete(accessor);
@@ -3753,7 +3773,8 @@ function writeHTMLResumeStatements(path) {
3753
3773
  for (const [accessor, varLoc] of getSectionDebugVars(section)) (debugVars ||= []).push(toObjectProperty(accessor, _marko_compiler.types.valueToNode(varLoc)));
3754
3774
  if (debugVars) writeScopeArgs.push(_marko_compiler.types.objectExpression(debugVars));
3755
3775
  }
3756
- body.push(_marko_compiler.types.expressionStatement(getExprIfWritten(section, sectionReason, writeScopeBuilder ? writeScopeBuilder(callRuntime("_scope", ...writeScopeArgs)) : callRuntime("_scope", ...writeScopeArgs))));
3776
+ const writeCall = writeScopeBuilder ? writeScopeBuilder(callRuntime("_scope", ...writeScopeArgs)) : callRuntime("_scope", ...writeScopeArgs);
3777
+ body.push(_marko_compiler.types.expressionStatement(getExprIfWritten(section, sectionReason, writeCall)));
3757
3778
  }
3758
3779
  if (!isResumedBranch(section) && (section.hasAbortSignal || !!section.referencedClosures || sectionReason && some(section.bindings, isLetBinding)) && markerGuard) {
3759
3780
  const call = callRuntime("_resume_branch", scopeIdIdentifier);
@@ -4540,7 +4561,7 @@ function initBranchSection(bodySection, branchExpr, branch) {
4540
4561
  }
4541
4562
  function resumeOwnerByMarkerWhenStatic(bodySection, nodeBinding) {
4542
4563
  const branchExprReason = findSlot(nodeBinding, 4)?.reason;
4543
- if (isStateReason(branchExprReason) && some(branchExprReason.state, hasResumableWriter) && isUnconditionalReason(findSectionSlot(bodySection, 9)?.reason) && isUnconditionalReason(findSlot(nodeBinding)?.reason)) setSectionOwnerResumedByMarker(bodySection);
4564
+ if (isStateReason(branchExprReason) && some(branchExprReason.state, hasResumableWriter) && isUnconditionalReason(getBranchWriteReason(bodySection)) && isUnconditionalReason(getWriteReason(nodeBinding))) setSectionOwnerResumedByMarker(bodySection);
4544
4565
  }
4545
4566
  function getBranchResumeArgs(tagSection, nodeBinding, branchReasons, onlyChildParentTagName, singleNode) {
4546
4567
  const endArgs = getBranchEndArgs(tagSection, nodeBinding, onlyChildParentTagName, singleNode);
@@ -4548,7 +4569,7 @@ function getBranchResumeArgs(tagSection, nodeBinding, branchReasons, onlyChildPa
4548
4569
  return [getWriteGuardForAny(tagSection, branchReasons, !markerGuard), ...endArgs];
4549
4570
  }
4550
4571
  function getBranchEndArgs(tagSection, nodeBinding, onlyChildParentTagName, singleNode) {
4551
- const markerReason = findSlot(nodeBinding)?.reason;
4572
+ const markerReason = getWriteReason(nodeBinding);
4552
4573
  const skipParentEnd = !!onlyChildParentTagName && !!markerReason;
4553
4574
  if (skipParentEnd) getBranchEndTags().add(nodeBinding);
4554
4575
  const branchExprGuard = skipParentEnd ? getWriteGuard(tagSection, findSlot(nodeBinding, 4)?.reason, false) : singleNode ? _marko_compiler.types.numericLiteral(0) : void 0;
@@ -4631,7 +4652,7 @@ const IfTag = {
4631
4652
  const [branchTag, branchBodySection] = branches[i];
4632
4653
  const bodyStatements = branchTag.node.body.body;
4633
4654
  if (branchBodySection) {
4634
- const branchReason = findSectionSlot(branchBodySection, 9)?.reason;
4655
+ const branchReason = getBranchWriteReason(branchBodySection);
4635
4656
  if (branchReason) {
4636
4657
  branchReasons = sourcesUtil.add(branchReasons, branchReason);
4637
4658
  bodyStatements.push(_marko_compiler.types.returnStatement(_marko_compiler.types.numericLiteral(i)));
@@ -4664,8 +4685,10 @@ const IfTag = {
4664
4685
  const [branchTag, branchBodySection] = branches[i];
4665
4686
  const [testAttr] = branchTag.node.attributes;
4666
4687
  const consequent = _marko_compiler.types.numericLiteral(branchBodySection ? i : -1);
4667
- if (branchBodySection) setClosureSignalBuilder(branchTag, (_closure, render) => {
4668
- return callRuntime("_if_closure", getScopeAccessorLiteral(nodeBinding, true), _marko_compiler.types.numericLiteral(i), render);
4688
+ if (branchBodySection) setClosureSignalBuilder(branchTag, {
4689
+ kind: "if",
4690
+ ref: nodeBinding,
4691
+ index: i
4669
4692
  });
4670
4693
  branchTag.remove();
4671
4694
  expr = testAttr ? _marko_compiler.types.conditionalExpression(testAttr.value, consequent, expr) : consequent;
@@ -5518,7 +5541,7 @@ var for_default = {
5518
5541
  const params = node.body.params;
5519
5542
  const statements = [];
5520
5543
  const bodyStatements = node.body.body;
5521
- const branchReason = findSectionSlot(bodySection, 9)?.reason;
5544
+ const branchReason = getBranchWriteReason(bodySection);
5522
5545
  resumeOwnerByMarkerWhenStatic(bodySection, nodeBinding);
5523
5546
  flushInto(tag);
5524
5547
  writeHTMLResumeStatements(tagBody);
@@ -5544,10 +5567,14 @@ var for_default = {
5544
5567
  const tagExtra = node.extra;
5545
5568
  const referencedBindings = getReferencedBindings(tagExtra);
5546
5569
  const nodeBinding = tagExtra.nodeBinding;
5547
- setClosureSignalBuilder(tag, (closure, render) => {
5570
+ const hop = {
5571
+ kind: "for",
5572
+ ref: nodeBinding
5573
+ };
5574
+ setClosureSignalBuilder(tag, hop, (closure, render) => {
5548
5575
  const selectorKeyBinding = getForSelectorKey(bodySection, closure);
5549
- if (selectorKeyBinding) return callRuntime("_for_selector", getScopeAccessorLiteral(nodeBinding, true), getScopeAccessorLiteral(closure, true), getScopeAccessorLiteral(selectorKeyBinding, true), render);
5550
- return callRuntime("_for_closure", getScopeAccessorLiteral(nodeBinding, true), render);
5576
+ if (!selectorKeyBinding) return buildClosureHop(hop, render);
5577
+ return callRuntime("_for_selector", getScopeAccessorLiteral(nodeBinding, true), getScopeAccessorLiteral(closure, true), getScopeAccessorLiteral(selectorKeyBinding, true), render);
5551
5578
  });
5552
5579
  const forType = getForType(node);
5553
5580
  const forAttrs = getKnownAttrValues(node);
@@ -6592,7 +6619,7 @@ function resolveReads(intersectionsBySection) {
6592
6619
  }
6593
6620
  forEach(exprBindings.lazyBindings, addAlwaysRead);
6594
6621
  } else forEach(reads, (read) => {
6595
- if (!read.inFunction && read.extra.exprRoot?.retained) addReasonExprs(getSlot(read.binding), expr);
6622
+ if (!read.fnRoot && read.extra.exprRoot?.retained) addReasonExprs(getSlot(read.binding), expr);
6596
6623
  });
6597
6624
  if (exprBindings.allBindings) {
6598
6625
  const exprFnReads = fnReadsByExpression.get(expr);
@@ -7961,7 +7988,7 @@ function addRead(exprExtra, extra, binding, section, getter) {
7961
7988
  ownVar: false,
7962
7989
  comparedTo: void 0,
7963
7990
  deferred: false,
7964
- inFunction: false
7991
+ fnRoot: void 0
7965
7992
  };
7966
7993
  if (section.pruned) return read;
7967
7994
  binding.reads.set(exprExtra, push(binding.reads.get(exprExtra), read));
@@ -8036,7 +8063,6 @@ function addReadToExpression(root, binding, getter) {
8036
8063
  }
8037
8064
  if (!getter && root.parent.type === "MarkoSpreadAttribute") extra.spreadFrom = binding;
8038
8065
  if (fnRoot) {
8039
- read.inFunction = true;
8040
8066
  read.deferred = fnRoot.node.type !== "ObjectMethod" || fnRoot.node.kind === "method";
8041
8067
  const fnReadsByExpr = getFunctionReadsByExpression();
8042
8068
  let exprFnReads = fnReadsByExpr.get(exprExtra);
@@ -8044,6 +8070,7 @@ function addReadToExpression(root, binding, getter) {
8044
8070
  const fnExtra = fnRoot.node.extra ??= {};
8045
8071
  fnExtra.section = section;
8046
8072
  fnExtra.exprRoot = rootExtra;
8073
+ read.fnRoot = fnExtra;
8047
8074
  exprFnReads.set(fnExtra, push(exprFnReads.get(fnExtra), read));
8048
8075
  }
8049
8076
  }
@@ -8844,7 +8871,7 @@ var html_comment_default = {
8844
8871
  const textLiteral = bodyToTextLiteral(tag.node.body);
8845
8872
  if (!_marko_compiler.types.isStringLiteral(textLiteral)) addStatement("render", tagSection, getReferencedBindings(tagExtra), _marko_compiler.types.expressionStatement(callRuntime("_text", createScopeReadExpression(nodeBinding), textLiteral)));
8846
8873
  }
8847
- if (nodeBinding) markNode(tag, nodeBinding, findSlot(nodeBinding)?.reason);
8874
+ if (nodeBinding) markNode(tag, nodeBinding, getWriteReason(nodeBinding));
8848
8875
  tag.remove();
8849
8876
  } },
8850
8877
  parseOptions: { text: true },
@@ -9335,11 +9362,12 @@ var show_default = {
9335
9362
  const singleNode = tagExtra[kSingleNodeBody];
9336
9363
  const endArgs = getBranchEndArgs(tagSection, nodeBinding, onlyChildParentTagName, singleNode);
9337
9364
  const showStart = singleNode ? callRuntime("_show_start", _marko_compiler.types.cloneNode(display, true), _marko_compiler.types.numericLiteral(0)) : callRuntime("_show_start", _marko_compiler.types.cloneNode(display, true), ...getBranchEndArgs(tagSection, nodeBinding, onlyChildParentTagName, singleNode));
9338
- for (const replacement of tag.replaceWithMultiple([
9365
+ const statements = [
9339
9366
  _marko_compiler.types.expressionStatement(showStart),
9340
9367
  ...bodyStatements,
9341
9368
  _marko_compiler.types.expressionStatement(callRuntime("_show_end", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), display, ...endArgs))
9342
- ])) replacement.skip();
9369
+ ];
9370
+ for (const replacement of tag.replaceWithMultiple(statements)) replacement.skip();
9343
9371
  }
9344
9372
  },
9345
9373
  dom: { exit(tag) {
@@ -9588,7 +9616,7 @@ function translateHTML(tag) {
9588
9616
  const binding = node.extra?.nodeBinding;
9589
9617
  if (binding) {
9590
9618
  writeTo$1(tag)`${callRuntime("_style_html", buildStyleDecls(node))}`;
9591
- markNode(tag, binding, findSlot(binding)?.reason);
9619
+ markNode(tag, binding, getWriteReason(binding));
9592
9620
  }
9593
9621
  emitStyleImport(tag);
9594
9622
  tag.remove();
@@ -9734,7 +9762,16 @@ var try_default = {
9734
9762
  const placeholderSection = placeholderTag && getSectionForBody(placeholderTag.get("body"));
9735
9763
  flushInto(tag);
9736
9764
  writeHTMLResumeStatements(tagBody);
9737
- tag.replaceWith(_marko_compiler.types.expressionStatement(callRuntime("_try", getScopeIdIdentifier(section), getScopeAccessorLiteral(nodeBinding), buildContent(tagBody), placeholderSection && buildContent(placeholderTag.get("body")), catchTag && (catchSection ? buildContent(catchTag.get("body")) : _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([]))), placeholderSection && _marko_compiler.types.stringLiteral(getResumeRegisterId(placeholderSection, "content")), catchTag && _marko_compiler.types.stringLiteral(catchSection ? getResumeRegisterId(catchSection, "content") : getEmptyCatchId(section, nodeBinding)))))[0].skip();
9765
+ const tryArgs = [
9766
+ getScopeIdIdentifier(section),
9767
+ getScopeAccessorLiteral(nodeBinding),
9768
+ buildContent(tagBody),
9769
+ placeholderSection && buildContent(placeholderTag.get("body")),
9770
+ catchTag && (catchSection ? buildContent(catchTag.get("body")) : _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([]))),
9771
+ placeholderSection && _marko_compiler.types.stringLiteral(getResumeRegisterId(placeholderSection, "content")),
9772
+ catchTag && _marko_compiler.types.stringLiteral(catchSection ? getResumeRegisterId(catchSection, "content") : getEmptyCatchId(section, nodeBinding))
9773
+ ];
9774
+ tag.replaceWith(_marko_compiler.types.expressionStatement(callRuntime("_try", ...tryArgs)))[0].skip();
9738
9775
  }
9739
9776
  },
9740
9777
  dom: { exit(tag) {
@@ -9961,7 +9998,7 @@ function translateExit(placeholder) {
9961
9998
  } else {
9962
9999
  const section = getSection(placeholder);
9963
10000
  const siblingText = extra[kSiblingText];
9964
- const markerReason = nodeBinding && findSlot(nodeBinding)?.reason;
10001
+ const markerReason = nodeBinding && getWriteReason(nodeBinding);
9965
10002
  if (isHTML) {
9966
10003
  if (markerReason) {
9967
10004
  const guard = getWriteGuard(section, markerReason, true);
@@ -10242,7 +10279,7 @@ var native_tag_default = {
10242
10279
  } else {
10243
10280
  assertValidNativeEventHandlerAttr(tag, attr);
10244
10281
  if (isChangeHandlerAttr) valueExtra.retained = true;
10245
- if (!isStaticDelimitedAttr(tag, attr) && !evaluate(attr.value).confident) {
10282
+ if (isDynamicAttr(tag, attr)) {
10246
10283
  hasDynamicAttributes = true;
10247
10284
  addSetupExpr(tagSection, attr.value);
10248
10285
  } else if (attr.name === "content" && tagName !== "meta") addSetupExpr(tagSection, attr.value);
@@ -10449,9 +10486,9 @@ var native_tag_default = {
10449
10486
  else if (contentAttr) {
10450
10487
  write`>`;
10451
10488
  htmlContentAttrTags.add(tag.node);
10452
- tag.node.body.body = [_marko_compiler.types.expressionStatement(callRuntime("_attr_content", visitAccessor, getScopeIdIdentifier(tagSection), contentAttr.value, getWriteGuard(tagSection, nodeBinding && findSlot(nodeBinding)?.reason, true)))];
10489
+ tag.node.body.body = [_marko_compiler.types.expressionStatement(callRuntime("_attr_content", visitAccessor, getScopeIdIdentifier(tagSection), contentAttr.value, getWriteGuard(tagSection, nodeBinding && getWriteReason(nodeBinding), true)))];
10453
10490
  } else if (spreadContent) {
10454
- const markerGuard = getWriteGuard(tagSection, nodeBinding && findSlot(nodeBinding)?.reason, true);
10491
+ const markerGuard = getWriteGuard(tagSection, nodeBinding && getWriteReason(nodeBinding), true);
10455
10492
  htmlContentAttrTags.add(tag.node);
10456
10493
  tag.node.body.body = [skipExpression ? _marko_compiler.types.expressionStatement(callRuntime("_attrs_partial_content", spreadExpression, skipExpression, visitAccessor, getScopeIdIdentifier(tagSection), _marko_compiler.types.stringLiteral(tagName), markerGuard)) : _marko_compiler.types.expressionStatement(callRuntime("_attrs_content", spreadExpression, visitAccessor, getScopeIdIdentifier(tagSection), _marko_compiler.types.stringLiteral(tagName), markerGuard))];
10457
10494
  } else write`>`;
@@ -10465,7 +10502,7 @@ var native_tag_default = {
10465
10502
  const tagName = getCanonicalTagName(tag);
10466
10503
  const tagSection = getSection(tag);
10467
10504
  const skipEndTag = isEndTagWrittenByBranch(nodeBinding);
10468
- const markerReason = !skipEndTag && nodeBinding && findSlot(nodeBinding)?.reason;
10505
+ const markerReason = !skipEndTag && nodeBinding && getWriteReason(nodeBinding);
10469
10506
  const write = writeTo$1(tag, tagName === "html" || !markerReason && tagName === "body");
10470
10507
  if (htmlContentAttrTags.has(tag.node)) flushBefore(tag);
10471
10508
  if (selectArgs) {
@@ -10947,6 +10984,9 @@ function assertUniqueClassToggles(tag, attr, { staticParts, dynamicValues = [] }
10947
10984
  function getClassNames(part) {
10948
10985
  return part === void 0 ? [] : isLiteralPart(part) ? part.split(/\s+/).filter(Boolean) : [part.join(".")];
10949
10986
  }
10987
+ function isDynamicAttr(tag, attr) {
10988
+ return !isStaticDelimitedAttr(tag, attr) && !evaluate(attr.value).confident;
10989
+ }
10950
10990
  function isStaticDelimitedAttr(tag, attr) {
10951
10991
  const { name, value } = attr;
10952
10992
  if (name !== "class" && name !== "style") return false;
@@ -11168,7 +11208,7 @@ var dynamic_tag_default = {
11168
11208
  const tagExtra = node.extra;
11169
11209
  const nodeBinding = tagExtra.nodeBinding;
11170
11210
  const isClassAPI = tagExtra.featureType === "class";
11171
- const markerReason = findSlot(nodeBinding)?.reason;
11211
+ const markerReason = getWriteReason(nodeBinding);
11172
11212
  let tagExpression = node.name;
11173
11213
  if (isClassAPI) {
11174
11214
  const classTagTemplate = (0, _marko_compiler_babel_utils.getTagTemplate)(tag);
@@ -11619,13 +11659,13 @@ function createInteropTranslator(translate5) {
11619
11659
  const entryFile = (0, _marko_compiler_babel_utils.getFile)();
11620
11660
  const { output, entry } = entryFile.markoOpts;
11621
11661
  if (!(output === "dom" && entry === "page" || output === "hydrate")) return enterProgram?.call(this, program, state);
11622
- const visitedFiles = /* @__PURE__ */ new Map([[(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, entryFile.opts.filename), false]]);
11623
- entryBuilder.visit(entryFile, entryFile, function visitChild(resolved, bundled = false) {
11624
- const seenBundled = visitedFiles.get(resolved);
11625
- if (seenBundled === false || seenBundled && bundled) return;
11626
- visitedFiles.set(resolved, bundled);
11662
+ const visitedFiles = /* @__PURE__ */ new Map([[(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, entryFile.opts.filename), 0]]);
11663
+ entryBuilder.visit(entryFile, entryFile, function visitChild(resolved, reach = 0) {
11664
+ const seen = visitedFiles.get(resolved);
11665
+ if (seen !== void 0 && seen <= reach) return;
11666
+ visitedFiles.set(resolved, reach);
11627
11667
  const file = (0, _marko_compiler_babel_utils.loadFileForImport)(entryFile, resolved);
11628
- if (file) entryBuilder.visit(file, entryFile, (id, childBundled = false) => visitChild(resolveRelativeToEntry(entryFile, file, id), childBundled || bundled));
11668
+ if (file) entryBuilder.visit(file, entryFile, (id, childReach = 0) => visitChild(resolveRelativeToEntry(entryFile, file, id), childReach > reach ? childReach : reach));
11629
11669
  });
11630
11670
  program.node.body = entryBuilder.build(entryFile);
11631
11671
  program.skip();
@@ -16,19 +16,26 @@ interface EntryState {
16
16
  * below a root everything arrives through its imports, and a lazy subtree
17
17
  * is loaded by its own load entry. */
18
18
  bundled: number;
19
+ /** Depth of enclosing lazy imports, whose load entries bring their assets. */
20
+ lazyDepth: number;
19
21
  roots: string[];
20
22
  /** Assets of templates the bundle never loads; the entry imports them. */
21
23
  assets: Set<string>;
22
24
  /** Assets that arrive through a bundled template's imports; the entry
23
25
  * imports them itself only when it links nothing (a server only page). */
24
26
  bundledAssets: Set<string>;
25
- /** Whether each reached file was only ever seen below a bundled template. */
26
- visited: Map<string, boolean>;
27
+ /** The most eager way each file has been reached. */
28
+ visited: Map<string, Reach>;
27
29
  }
30
+ /** How a file was reached: 0 eagerly, 1 below a bundled template, 2 only
31
+ * within a lazy subtree. Lower is more eager, so `seen <= reach` means it was
32
+ * already visited at least as eagerly and is skipped; a file reached more
33
+ * eagerly than before is re-visited, since it may then own assets or a root. */
34
+ export type Reach = 0 | 1 | 2;
28
35
  type EntryFile = t.BabelFile & {
29
36
  [kState]?: EntryState;
30
37
  };
31
- type VisitChild = (id: string, bundled?: boolean) => void;
38
+ type VisitChild = (id: string, reach?: Reach) => void;
32
39
  declare const kState: unique symbol;
33
40
  declare const builder: {
34
41
  build(entryFile: EntryFile, exportInit?: boolean): t.Statement[];
@@ -12,7 +12,8 @@ export interface Read {
12
12
  getter: Getter | undefined;
13
13
  comparedTo: t.Node | undefined;
14
14
  deferred: boolean;
15
- inFunction: boolean;
15
+ /** The outermost function holding it; none when that escapes into a call. */
16
+ fnRoot: ReferencedFunctionExtra | undefined;
16
17
  }
17
18
  export interface ExtraRead {
18
19
  binding: Binding;
@@ -33,8 +33,17 @@ export interface Signal {
33
33
  buildAssignment: ((valueSection: Section, value: t.Expression) => t.Expression | undefined) | undefined;
34
34
  }
35
35
  type closureSignalBuilder = (closure: Binding, render: t.Expression) => t.Expression;
36
+ export type ClosureHop = {
37
+ kind: "if";
38
+ ref: Binding;
39
+ index: number;
40
+ } | {
41
+ kind: "for";
42
+ ref: Binding;
43
+ };
36
44
  export declare const getSignals: (section: Section) => Map<unknown, Signal>;
37
- export declare function setClosureSignalBuilder(tag: t.NodePath<t.MarkoTag>, builder: closureSignalBuilder): void;
45
+ export declare function setClosureSignalBuilder(tag: t.NodePath<t.MarkoTag>, hop: ClosureHop, build?: closureSignalBuilder): void;
46
+ export declare function buildClosureHop(hop: ClosureHop, render: t.Expression): t.CallExpression;
38
47
  export declare function setSectionOwnerResumedByMarker(section: Section): void;
39
48
  export declare function getContentClosureValues(bodySection: Section): {
40
49
  scope: t.Identifier;
@@ -1,12 +1,16 @@
1
1
  import { types as t } from "@marko/compiler";
2
+ import { type Binding } from "./bindings";
2
3
  import { type Reason, type Reasons } from "./reasons";
3
4
  import { type Section } from "./sections";
5
+ import { type Sources } from "./sources";
4
6
  export declare function isSameReason(a: Reason | undefined, b: Reason | undefined): boolean;
5
7
  export declare function buildGroupMask(groups: {
6
8
  value: number | t.Expression | undefined;
7
9
  names: string;
8
10
  }[]): t.Expression | undefined;
9
11
  export declare function getScopeReasonStatement(section: Section): t.Statement;
12
+ export declare function getWriteReason(binding: Binding): Sources | undefined;
13
+ export declare function getBranchWriteReason(section: Section): Sources | undefined;
10
14
  export declare function getWriteGuard(section: Section, reason: undefined | Reason, optional: boolean): t.Expression | undefined;
11
15
  export declare function getWriteGuardForAny(section: Section, reasons: undefined | Reasons, optional: boolean): t.Expression | undefined;
12
16
  export declare function getExprIfWritten<T extends undefined | Reason, R extends (T extends {} ? t.Expression : undefined)>(section: Section, reason: T, expr: t.Expression): R;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marko",
3
- "version": "6.4.4",
3
+ "version": "6.4.5",
4
4
  "description": "Optimized runtime for Marko templates.",
5
5
  "keywords": [
6
6
  "api",
@@ -57,8 +57,8 @@
57
57
  "magic-string": "^0.30.21"
58
58
  },
59
59
  "devDependencies": {
60
- "@marko/runtime-tags": "npm:marko@6.4.4",
61
- "marko": "5.39.45"
60
+ "@marko/runtime-tags": "npm:marko@6.4.5",
61
+ "marko": "5.39.46"
62
62
  },
63
63
  "engines": {
64
64
  "node": ">=22"