marko 6.1.2 → 6.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/common/accessor.d.ts +5 -0
  2. package/dist/common/accessor.debug.d.ts +5 -0
  3. package/dist/common/compat-meta.d.ts +0 -1
  4. package/dist/common/opt.d.ts +3 -1
  5. package/dist/common/types.d.ts +1 -1
  6. package/dist/debug/dom.js +315 -122
  7. package/dist/debug/dom.mjs +306 -123
  8. package/dist/debug/html.js +922 -712
  9. package/dist/debug/html.mjs +920 -713
  10. package/dist/dom/compat.d.ts +3 -2
  11. package/dist/dom/control-flow.d.ts +2 -1
  12. package/dist/dom/load.d.ts +23 -0
  13. package/dist/dom/queue.d.ts +4 -2
  14. package/dist/dom/resume.d.ts +10 -8
  15. package/dist/dom/signals.d.ts +4 -3
  16. package/dist/dom.d.ts +3 -2
  17. package/dist/dom.js +195 -66
  18. package/dist/dom.mjs +195 -66
  19. package/dist/html/assets.d.ts +47 -0
  20. package/dist/html/compat.d.ts +3 -2
  21. package/dist/html/inlined-runtimes.d.ts +1 -1
  22. package/dist/html/inlined-runtimes.debug.d.ts +1 -1
  23. package/dist/html/serializer.d.ts +14 -9
  24. package/dist/html/writer.d.ts +34 -15
  25. package/dist/html.d.ts +1 -0
  26. package/dist/html.js +502 -345
  27. package/dist/html.mjs +502 -345
  28. package/dist/translator/index.d.ts +1 -0
  29. package/dist/translator/index.js +342 -76
  30. package/dist/translator/interop/index.d.ts +1 -0
  31. package/dist/translator/util/marko-config.d.ts +2 -0
  32. package/dist/translator/util/references.d.ts +1 -5
  33. package/dist/translator/util/runtime.d.ts +1 -0
  34. package/dist/translator/util/tag-name-type.d.ts +2 -0
  35. package/dist/translator/util/walks.d.ts +1 -1
  36. package/dist/translator/visitors/import-declaration.d.ts +10 -1
  37. package/dist/translator/visitors/tag/custom-tag.d.ts +7 -0
  38. package/package.json +2 -2
package/dist/debug/dom.js CHANGED
@@ -263,8 +263,8 @@ function schedule() {
263
263
  }
264
264
  }
265
265
  function flushAndWaitFrame() {
266
- runTask();
267
266
  requestAnimationFrame(triggerMacroTask);
267
+ runTask();
268
268
  }
269
269
  function triggerMacroTask() {
270
270
  if (!channel) {
@@ -284,29 +284,41 @@ function triggerMacroTask() {
284
284
  //#region src/dom/signals.ts
285
285
  function _let(id, fn) {
286
286
  const valueAccessor = id.slice(0, id.lastIndexOf("/"));
287
- const valueChangeAccessor = "TagVariableChange:" + valueAccessor;
288
287
  id = +id.slice(id.lastIndexOf("/") + 1);
289
- return (scope, value, valueChange) => {
288
+ return (scope, value) => {
290
289
  if (rendering) {
291
- if ((scope[valueChangeAccessor] = valueChange) && scope[valueAccessor] !== value || scope["#Creating"]) {
290
+ if (scope["#Creating"]) {
292
291
  scope[valueAccessor] = value;
293
292
  fn?.(scope);
294
293
  }
295
- } else if (scope[valueChangeAccessor]) scope[valueChangeAccessor](value);
296
- else if (scope[valueAccessor] !== (scope[valueAccessor] = value) && fn) {
294
+ } else if ((scope[valueAccessor] !== value || !(valueAccessor in scope)) && (scope[valueAccessor] = value, fn)) {
297
295
  schedule();
298
296
  queueRender(scope, fn, id);
299
297
  }
300
298
  return value;
301
299
  };
302
300
  }
301
+ function _let_change(id, fn) {
302
+ const valueAccessor = id.slice(0, id.lastIndexOf("/"));
303
+ const valueChangeAccessor = "TagVariableChange:" + valueAccessor;
304
+ const base = _let(id, fn);
305
+ return (scope, value, valueChange) => {
306
+ if (rendering) if ((scope[valueChangeAccessor] = valueChange) && (scope[valueAccessor] !== value || !(valueAccessor in scope))) {
307
+ scope[valueAccessor] = value;
308
+ fn?.(scope);
309
+ } else base(scope, value);
310
+ else if (scope[valueChangeAccessor]) scope[valueChangeAccessor](value);
311
+ else base(scope, value);
312
+ return value;
313
+ };
314
+ }
303
315
  function _const(valueAccessor, fn) {
304
- return (scope, value) => {
305
- if (scope["#Creating"] || scope[valueAccessor] !== value) {
316
+ return ((scope, value) => {
317
+ if (scope[valueAccessor] !== value || !(valueAccessor in scope)) {
306
318
  scope[valueAccessor] = value;
307
319
  fn?.(scope);
308
320
  }
309
- };
321
+ });
310
322
  }
311
323
  function _or(id, fn, defaultPending = 1, scopeIdAccessor = "#Id") {
312
324
  return (scope) => {
@@ -542,53 +554,73 @@ function createCloneableHTML(html, ns) {
542
554
  //#endregion
543
555
  //#region src/dom/resume.ts
544
556
  const registeredValues = {};
545
- let curRuntimeId;
546
- let readyLookup;
557
+ let curRenders;
547
558
  let branchesEnabled;
548
- let embedEnabled;
559
+ let embedRenders;
560
+ let readyIds;
549
561
  function enableBranches() {
550
- branchesEnabled = 1;
562
+ if (!branchesEnabled) {
563
+ branchesEnabled = 1;
564
+ skipDestroyedRenders();
565
+ }
551
566
  }
552
- const ready = /* @__PURE__ */ ((_) => (id) => {
553
- const cb = readyLookup[id];
554
- readyLookup[id] = 1;
555
- cb?.();
556
- })(readyLookup = {});
557
- function initEmbedded(readyId, runtimeId) {
558
- embedEnabled = 1;
559
- ready(readyId);
567
+ function ready(readyId, runtimeId) {
568
+ (readyIds ||= /* @__PURE__ */ new Set()).add(readyId);
560
569
  init(runtimeId);
561
- new MutationObserver(() => {
562
- const renders = self[curRuntimeId];
563
- for (const renderId in renders) {
564
- const { s, n } = renders[renderId];
565
- if (n && !n.isConnected) {
566
- delete renders[renderId];
567
- for (const id in s) destroyScope(s[id]);
570
+ for (const renderId in curRenders) runResumeEffects(curRenders[renderId]);
571
+ }
572
+ function initEmbedded(readyId, runtimeId) {
573
+ if (!embedRenders) {
574
+ embedRenders = /* @__PURE__ */ new Map();
575
+ new MutationObserver(() => {
576
+ for (const [anchor, [renderId, scopes]] of embedRenders) if (!anchor.isConnected) {
577
+ embedRenders.delete(anchor);
578
+ delete curRenders[renderId];
579
+ for (const id in scopes) destroyScope(scopes[id]);
568
580
  }
569
- }
570
- }).observe(document.body, {
571
- childList: true,
572
- subtree: true
573
- });
581
+ }).observe(document, {
582
+ childList: true,
583
+ subtree: true
584
+ });
585
+ }
586
+ ready(readyId, runtimeId);
574
587
  }
575
588
  function init(runtimeId = "M") {
576
- if (curRuntimeId) {
577
- if (curRuntimeId !== runtimeId) throw new Error(`Marko initialized multiple times with different $global.runtimeId's of ${JSON.stringify(runtimeId)} and ${JSON.stringify(curRuntimeId)}.`);
589
+ if (curRenders) {
590
+ if (curRenders !== self[runtimeId]) throw new Error(`Marko initialized multiple times with different $global.runtimeId's.`);
578
591
  return;
579
592
  }
580
- curRuntimeId = runtimeId;
581
- let resumeRender;
582
593
  const renders = self[runtimeId];
583
594
  const defineRuntime = (desc) => Object.defineProperty(self, runtimeId, desc);
584
595
  const initRuntime = (renders) => {
585
- defineRuntime({ value: resumeRender = ((renderId) => {
586
- const render = resumeRender[renderId] = renders[renderId] || renders(renderId);
596
+ defineRuntime({ value: curRenders = ((renderId) => {
597
+ const render = curRenders[renderId] = renders[renderId] || renders(renderId);
587
598
  const walk = render.w;
588
- const scopeLookup = render.s = {};
589
- const getScope = (id) => scopeLookup[id] ||= { ["#Id"]: +id };
590
- const serializeContext = { _: registeredValues };
591
- const visitBranches = branchesEnabled && ((branchScopesStack = [], branchStarts = [], orphanBranches = [], curBranchScopes) => {
599
+ const scopeLookup = {};
600
+ const getScope = (id) => scopeLookup[id] || initScope(scopeLookup[id] = { ["#Id"]: +id });
601
+ const initGlobal = () => $global ||= {
602
+ runtimeId,
603
+ renderId
604
+ };
605
+ const initScope = (scope) => {
606
+ scope["$global"] = initGlobal();
607
+ if (branchesEnabled && scope["#ClosestBranchId"]) scope["#ClosestBranch"] = getScope(scope["#ClosestBranchId"]);
608
+ return scope;
609
+ };
610
+ const applyScopes = (partials) => {
611
+ let scopeId = partials[0];
612
+ for (let i = 1; i < partials.length; i++) {
613
+ const partial = partials[i];
614
+ if (typeof partial === "number") scopeId += partial;
615
+ else {
616
+ if (scopeId) initScope(Object.assign(scopeLookup[scopeId] ||= (partial["#Id"] = scopeId, partial), partial));
617
+ else Object.assign(initGlobal(), partial);
618
+ scopeId++;
619
+ }
620
+ }
621
+ };
622
+ const serializeContext = ((data, registryId) => typeof data === "number" ? registryId ? registeredValues[registryId](getScope(data)) : getScope(data) : applyScopes(data));
623
+ const createVisitBranches = (branchScopesStack = [], branchStarts = [], orphanBranches = [], curBranchScopes) => {
592
624
  return (branchId, branch, endedBranches, accessor, singleNode, parent = visit.parentNode, startVisit = visit, i = orphanBranches.length) => {
593
625
  if (visitType !== "[") {
594
626
  visitScope[nextToken()] = visitType === ")" || visitType === "}" ? parent : visit;
@@ -619,7 +651,7 @@ function init(runtimeId = "M") {
619
651
  nextToken();
620
652
  }
621
653
  if (endedBranches) {
622
- orphanBranches.push(...endedBranches);
654
+ for (const ended of endedBranches) orphanBranches.push(ended);
623
655
  if (singleNode) visitScope[accessor] = endedBranches.length > 1 ? endedBranches.reverse() : endedBranches[0];
624
656
  }
625
657
  if (visitType === "[") {
@@ -630,46 +662,51 @@ function init(runtimeId = "M") {
630
662
  branchStarts.push(visit);
631
663
  }
632
664
  };
633
- })();
665
+ };
634
666
  const nextToken = () => lastToken = visitText.slice(lastTokenIndex, (lastTokenIndex = visitText.indexOf(" ", lastTokenIndex) + 1 || visitText.length + 1) - 1);
667
+ const processResumes = (resumes = [], effects) => {
668
+ let i = 0;
669
+ for (; i < resumes.length; i++) {
670
+ const serialized = resumes[i];
671
+ if (typeof serialized === "string") {
672
+ lastTokenIndex = 0;
673
+ visitText = serialized;
674
+ while (nextToken()) if (/\D/.test(lastToken)) lastEffect = registeredValues[lastToken];
675
+ else effects.push(lastEffect, getScope(lastToken));
676
+ } else if (Array.isArray(serialized)) {
677
+ if (!(readyIds && serialized.every((dep) => readyIds.has(dep) && !render.b[dep].length))) break;
678
+ } else if (readyIds && typeof serialized === "number") break;
679
+ else {
680
+ const scopes = serialized(serializeContext);
681
+ if (Array.isArray(scopes)) applyScopes(scopes);
682
+ }
683
+ }
684
+ resumes.splice(0, i);
685
+ return i;
686
+ };
635
687
  let $global;
636
688
  let lastEffect;
637
689
  let visits;
638
- let resumes;
639
690
  let visit;
640
691
  let visitText;
641
692
  let visitType;
642
693
  let visitScope;
643
694
  let lastToken;
644
695
  let lastTokenIndex;
645
- let lastScopeId = 0;
696
+ let visitBranches;
697
+ let embedAnchor;
698
+ serializeContext._ = registeredValues;
646
699
  if (render.m) throw new Error(`Marko rendered multiple times with $global.runtimeId as ${JSON.stringify(runtimeId)} and $global.renderId as ${JSON.stringify(renderId)}. Ensure each render into a page has a unique $global.renderId.`);
647
- render.m = (effects = []) => {
648
- if (readyLookup) {
649
- for (const readyId in render.b) if (readyLookup[readyId] !== 1) {
650
- readyLookup[readyId] = ((prev) => () => {
651
- runResumeEffects(render);
652
- prev?.();
653
- })(readyLookup[readyId]);
654
- return effects;
700
+ render.m = (effects) => {
701
+ processResumes(render.r, effects);
702
+ if (readyIds && render.b) for (let progress = 1; progress;) {
703
+ progress = 0;
704
+ for (const readyId of readyIds) {
705
+ const resumes = render.b[readyId];
706
+ if (resumes && processResumes(resumes, effects)) progress = 1;
655
707
  }
656
- render.b = 0;
657
- }
658
- for (const serialized of resumes = render.r || []) if (typeof serialized === "string") {
659
- lastTokenIndex = 0;
660
- visitText = serialized;
661
- while (nextToken()) if (/\D/.test(lastToken)) lastEffect = registeredValues[lastToken];
662
- else effects.push(lastEffect, getScope(lastToken));
663
- } else for (const scope of serialized(serializeContext)) if (!$global) {
664
- $global = scope || {};
665
- $global.runtimeId = runtimeId;
666
- $global.renderId = renderId;
667
- } else if (typeof scope === "number") lastScopeId += scope;
668
- else {
669
- scopeLookup[scope["#Id"] = ++lastScopeId] = scope;
670
- scope["$global"] = $global;
671
- if (branchesEnabled) scope["#ClosestBranch"] = getScope(scope["#ClosestBranchId"]);
672
708
  }
709
+ let retained = 0;
673
710
  for (visit of visits = render.v) {
674
711
  lastTokenIndex = render.i.length;
675
712
  visitText = visit.data;
@@ -678,10 +715,11 @@ function init(runtimeId = "M") {
678
715
  if (visitType === "*") {
679
716
  const prev = visit.previousSibling;
680
717
  visitScope[nextToken()] = prev && (prev.nodeType < 8 || prev.data) ? prev : visit.parentNode.insertBefore(new Text(), visit);
681
- } else if (branchesEnabled) visitBranches();
718
+ } else if (branchesEnabled) (visitBranches ||= createVisitBranches())();
719
+ else if (render.b) visits[retained++] = visit;
682
720
  }
683
- if (embedEnabled) render.n ||= visit?.parentNode.insertBefore(new Text(), visit.nextSibling);
684
- visits.length = resumes.length = 0;
721
+ if (embedRenders && !embedAnchor && visit) embedRenders.set(embedAnchor = visit.parentNode.insertBefore(new Text(), visit.nextSibling), [renderId, scopeLookup]);
722
+ visits.length = retained;
685
723
  return effects;
686
724
  };
687
725
  render.w = () => {
@@ -693,7 +731,7 @@ function init(runtimeId = "M") {
693
731
  };
694
732
  if (renders) {
695
733
  initRuntime(renders);
696
- for (const renderId in renders) runResumeEffects(resumeRender(renderId));
734
+ for (const renderId in renders) runResumeEffects(curRenders(renderId));
697
735
  } else defineRuntime({
698
736
  configurable: true,
699
737
  set: initRuntime
@@ -703,7 +741,7 @@ let isResuming;
703
741
  function runResumeEffects(render) {
704
742
  try {
705
743
  isResuming = 1;
706
- runEffects(render.m(), 1);
744
+ runEffects(render.m([]), 1);
707
745
  } finally {
708
746
  isResuming = 0;
709
747
  }
@@ -1172,50 +1210,41 @@ function _await_promise(nodeAccessor, params) {
1172
1210
  _enable_catch();
1173
1211
  return (scope, promise) => {
1174
1212
  let awaitBranch = scope[branchAccessor];
1175
- const tryBranch = findBranchWithKey(scope, "#PlaceholderContent") || awaitBranch;
1213
+ const tryPlaceholder = findBranchWithKey(scope, "#PlaceholderContent");
1214
+ const tryBranch = tryPlaceholder || awaitBranch;
1176
1215
  let awaitCounter = tryBranch["#AwaitCounter"];
1177
- if (!awaitCounter?.i) awaitCounter = tryBranch["#AwaitCounter"] = {
1178
- i: 0,
1179
- c() {
1180
- if (--awaitCounter.i) return 1;
1181
- if (tryBranch === scope[branchAccessor]) {
1182
- if (scope[nodeAccessor].parentNode) scope[nodeAccessor].replaceWith(scope[branchAccessor]["#StartNode"].parentNode);
1183
- } else {
1184
- const placeholderBranch = tryBranch["#PlaceholderBranch"];
1185
- if (placeholderBranch) {
1186
- tryBranch["#PlaceholderBranch"] = 0;
1187
- placeholderBranch["#StartNode"].parentNode.insertBefore(tryBranch["#StartNode"].parentNode, placeholderBranch["#StartNode"]);
1188
- removeAndDestroyBranch(placeholderBranch);
1189
- }
1216
+ placeholderShown.add(pendingEffects);
1217
+ if (tryPlaceholder) {
1218
+ if (!scope[promiseAccessor]) {
1219
+ if (awaitBranch) awaitBranch["#PendingRenders"] ||= [];
1220
+ awaitCounter = addAwaitCounter(scope, tryPlaceholder);
1221
+ }
1222
+ } else {
1223
+ if (!awaitCounter?.i) awaitCounter = tryBranch["#AwaitCounter"] = {
1224
+ i: 0,
1225
+ c() {
1226
+ if (--awaitCounter.i) return 1;
1227
+ if (tryBranch === scope[branchAccessor]) {
1228
+ if (scope[nodeAccessor].parentNode) scope[nodeAccessor].replaceWith(scope[branchAccessor]["#StartNode"].parentNode);
1229
+ } else dismissPlaceholder(tryBranch);
1230
+ queueEffect(tryBranch, runPendingEffects);
1190
1231
  }
1191
- queueEffect(tryBranch, (scope) => {
1192
- const pendingEffects = scope["#PendingEffects"];
1193
- if (pendingEffects) {
1194
- scope["#PendingEffects"] = [];
1195
- runEffects(pendingEffects, 1);
1232
+ };
1233
+ if (!scope[promiseAccessor]) {
1234
+ if (awaitBranch) awaitBranch["#PendingRenders"] ||= [];
1235
+ if (!awaitCounter.i++) requestAnimationFrame(() => awaitCounter.i && runEffects(prepareEffects(() => queueRender(scope, () => {
1236
+ if (!awaitBranch["#DetachedAwait"]) {
1237
+ awaitBranch["#StartNode"].parentNode.insertBefore(scope[nodeAccessor], awaitBranch["#StartNode"]);
1238
+ tempDetachBranch(tryBranch);
1196
1239
  }
1197
- });
1240
+ }, -1))));
1198
1241
  }
1199
- };
1200
- placeholderShown.add(pendingEffects);
1201
- if (!scope[promiseAccessor]) {
1202
- if (awaitBranch) awaitBranch["#PendingRenders"] ||= [];
1203
- if (!awaitCounter.i++) requestAnimationFrame(() => awaitCounter.i && runEffects(prepareEffects(() => queueRender(tryBranch === awaitBranch ? scope : tryBranch, () => {
1204
- if (tryBranch["#PlaceholderContent"]) {
1205
- insertBranchBefore(tryBranch["#PlaceholderBranch"] = createAndSetupBranch(scope["$global"], tryBranch["#PlaceholderContent"], tryBranch["_"], tryBranch["#StartNode"].parentNode), tryBranch["#StartNode"].parentNode, tryBranch["#StartNode"]);
1206
- tempDetachBranch(tryBranch);
1207
- } else if (!awaitBranch["#DetachedAwait"]) {
1208
- awaitBranch["#StartNode"].parentNode.insertBefore(scope[nodeAccessor], awaitBranch["#StartNode"]);
1209
- tempDetachBranch(tryBranch);
1210
- }
1211
- }, -1))));
1212
1242
  }
1213
1243
  const thisPromise = scope[promiseAccessor] = promise.then((data) => {
1214
1244
  if (thisPromise === scope[promiseAccessor]) {
1215
1245
  const referenceNode = scope[nodeAccessor];
1216
1246
  scope[promiseAccessor] = 0;
1217
- queueMicrotask(run);
1218
- queueRender(scope, () => {
1247
+ queueAsyncRender(scope, () => {
1219
1248
  if ((awaitBranch = scope[branchAccessor])["#DetachedAwait"]) {
1220
1249
  pendingScopes.push(awaitBranch);
1221
1250
  setupBranch(awaitBranch["#DetachedAwait"], awaitBranch);
@@ -1231,7 +1260,7 @@ function _await_promise(nodeAccessor, params) {
1231
1260
  awaitCounter.c();
1232
1261
  if (awaitCounter.m) {
1233
1262
  const fnScopes = /* @__PURE__ */ new Map();
1234
- const effects = awaitCounter.m();
1263
+ const effects = awaitCounter.m([]);
1235
1264
  for (let i = 0; i < pendingEffects.length;) {
1236
1265
  const fn = pendingEffects[i++];
1237
1266
  let scopes = fnScopes.get(fn);
@@ -1244,13 +1273,12 @@ function _await_promise(nodeAccessor, params) {
1244
1273
  if (!fnScopes.get(fn)?.has(scope)) queueEffect(scope, fn);
1245
1274
  }
1246
1275
  }
1247
- }, -1);
1276
+ });
1248
1277
  }
1249
1278
  }, (error) => {
1250
1279
  if (thisPromise === scope[promiseAccessor]) {
1251
1280
  awaitCounter.i = scope[promiseAccessor] = 0;
1252
- schedule();
1253
- queueRender(scope, renderCatch, -1, error);
1281
+ queueAsyncRender(scope, renderCatch, error);
1254
1282
  }
1255
1283
  });
1256
1284
  };
@@ -1263,6 +1291,39 @@ function _await_content(nodeAccessor, template, walks, setup) {
1263
1291
  pendingScopes.pop();
1264
1292
  };
1265
1293
  }
1294
+ function addAwaitCounter(scope, tryBranch = findBranchWithKey(scope, "#PlaceholderContent")) {
1295
+ if (!tryBranch) return;
1296
+ let awaitCounter = tryBranch["#AwaitCounter"];
1297
+ if (!awaitCounter?.i) awaitCounter = tryBranch["#AwaitCounter"] = {
1298
+ i: 0,
1299
+ c() {
1300
+ if (--awaitCounter.i) return 1;
1301
+ dismissPlaceholder(tryBranch);
1302
+ queueEffect(tryBranch, runPendingEffects);
1303
+ }
1304
+ };
1305
+ placeholderShown.add(pendingEffects);
1306
+ if (!awaitCounter.i++) requestAnimationFrame(() => awaitCounter.i && runEffects(prepareEffects(() => queueRender(tryBranch, () => {
1307
+ insertBranchBefore(tryBranch["#PlaceholderBranch"] = createAndSetupBranch(tryBranch["$global"], tryBranch["#PlaceholderContent"], tryBranch["_"], tryBranch["#StartNode"].parentNode), tryBranch["#StartNode"].parentNode, tryBranch["#StartNode"]);
1308
+ tempDetachBranch(tryBranch);
1309
+ }, -1))));
1310
+ return awaitCounter;
1311
+ }
1312
+ function runPendingEffects(scope) {
1313
+ const effects = scope["#PendingEffects"];
1314
+ if (effects) {
1315
+ scope["#PendingEffects"] = [];
1316
+ runEffects(effects, 1);
1317
+ }
1318
+ }
1319
+ function dismissPlaceholder(tryBranch) {
1320
+ const placeholderBranch = tryBranch["#PlaceholderBranch"];
1321
+ if (placeholderBranch) {
1322
+ tryBranch["#PlaceholderBranch"] = 0;
1323
+ placeholderBranch["#StartNode"].parentNode.insertBefore(tryBranch["#StartNode"].parentNode, placeholderBranch["#StartNode"]);
1324
+ removeAndDestroyBranch(placeholderBranch);
1325
+ }
1326
+ }
1266
1327
  function _try(nodeAccessor, template, walks, setup) {
1267
1328
  const branchAccessor = "BranchScopes:" + nodeAccessor;
1268
1329
  const renderer = _content("", template, walks, setup)();
@@ -1541,6 +1602,10 @@ function run() {
1541
1602
  }
1542
1603
  runEffects(effects);
1543
1604
  }
1605
+ function queueAsyncRender(scope, signal, value) {
1606
+ queueRender(scope, signal, -1, value);
1607
+ queueMicrotask(run);
1608
+ }
1544
1609
  function prepareEffects(fn) {
1545
1610
  const prevRenders = pendingRenders;
1546
1611
  const prevEffects = pendingEffects;
@@ -1585,12 +1650,17 @@ function runRenders() {
1585
1650
  }
1586
1651
  pendingRenders[i] = item;
1587
1652
  }
1588
- if (!render["scope"]["#ClosestBranch"]?.["#Destroyed"]) runRender(render);
1653
+ runRender(render);
1589
1654
  }
1590
1655
  for (const scope of pendingScopes) scope["#Creating"] = 0;
1591
1656
  pendingScopes = [];
1592
1657
  }
1593
1658
  let runRender = (render) => render["signal"](render["scope"], render["value"]);
1659
+ function skipDestroyedRenders() {
1660
+ runRender = ((runRender) => (render) => {
1661
+ if (!render["scope"]["#ClosestBranch"]?.["#Destroyed"]) runRender(render);
1662
+ })(runRender);
1663
+ }
1594
1664
  let catchEnabled;
1595
1665
  function _enable_catch() {
1596
1666
  if (!catchEnabled) {
@@ -1651,23 +1721,33 @@ function abort(ctrl) {
1651
1721
  }
1652
1722
  //#endregion
1653
1723
  //#region src/common/compat-meta.ts
1654
- const RENDERER_REGISTER_ID = "$compat_renderer";
1655
1724
  const SET_SCOPE_REGISTER_ID = "$compat_setScope";
1656
1725
  const RENDER_BODY_ID = "$compat_renderBody";
1657
1726
  //#endregion
1658
1727
  //#region src/dom/compat.ts
1659
1728
  const classIdToBranch = /* @__PURE__ */ new Map();
1729
+ const scopesByRender = /* @__PURE__ */ new WeakMap();
1730
+ const getRenderScopes = ($global) => {
1731
+ const render = self[$global.runtimeId]?.[$global.renderId];
1732
+ let scopes = render && scopesByRender.get(render);
1733
+ if (render && !scopes) scopesByRender.set(render, scopes = {});
1734
+ return scopes;
1735
+ };
1660
1736
  const compat = {
1661
1737
  patchDynamicTag,
1662
1738
  queueEffect,
1663
1739
  init(warp10Noop) {
1664
- _resume(SET_SCOPE_REGISTER_ID, (branch) => {
1665
- classIdToBranch.set(branch.m5c, branch);
1740
+ _resume(SET_SCOPE_REGISTER_ID, (scope) => {
1741
+ getRenderScopes(scope["$global"])[scope["#Id"]] = scope;
1742
+ if (scope.m5c) classIdToBranch.set(scope.m5c, scope);
1666
1743
  });
1667
1744
  _resume(RENDER_BODY_ID, warp10Noop);
1668
1745
  },
1669
- registerRenderer(fn) {
1670
- _resume(RENDERER_REGISTER_ID, fn);
1746
+ getScope($global, scopeId) {
1747
+ return getRenderScopes($global)?.[scopeId];
1748
+ },
1749
+ setRendererId(renderer, id) {
1750
+ renderer["id"] = id;
1671
1751
  },
1672
1752
  isRenderer(renderer) {
1673
1753
  return renderer["clone"];
@@ -1686,7 +1766,7 @@ const compat = {
1686
1766
  if (this.scope) destroyBranch(this.scope);
1687
1767
  },
1688
1768
  resolveRegistered(value, $global) {
1689
- if (Array.isArray(value) && typeof value[0] === "string") return getRegisteredWithScope(value[0], value.length === 2 && self[$global.runtimeId]?.[$global.renderId]?.s[value[1]]);
1769
+ if (Array.isArray(value) && typeof value[0] === "string") return getRegisteredWithScope(value[0], getRenderScopes($global)?.[value[1]]);
1690
1770
  return value;
1691
1771
  },
1692
1772
  createRenderer(params, clone) {
@@ -1792,6 +1872,109 @@ function mount(input = {}, reference, position) {
1792
1872
  };
1793
1873
  }
1794
1874
  //#endregion
1875
+ //#region src/dom/load.ts
1876
+ function _load_template(id, load) {
1877
+ _enable_catch();
1878
+ let pending;
1879
+ const lazyTemplate = _template(id, 0, 0, (branch) => {
1880
+ const awaitCounter = addAwaitCounter(branch);
1881
+ branch["#Load"] ||= /* @__PURE__ */ new Map();
1882
+ (pending ||= load()).then((renderer) => {
1883
+ Object.assign(lazyTemplate, renderer);
1884
+ queueAsyncRender(branch, (branch) => insertLoaded(renderer, branch, branch["#StartNode"], awaitCounter));
1885
+ }, loadFailed(branch, awaitCounter));
1886
+ }, _load_signal(() => (pending ||= load()).then((r) => ({ _: r["params"] }))));
1887
+ return lazyTemplate;
1888
+ }
1889
+ function _load_setup(nodeAccessor, childScopeAccessor, load) {
1890
+ let pending;
1891
+ let renderer;
1892
+ _enable_catch();
1893
+ return (owner) => {
1894
+ const child = owner[childScopeAccessor];
1895
+ if (renderer) insertLoaded(renderer, child, owner[nodeAccessor]);
1896
+ else {
1897
+ const awaitCounter = addAwaitCounter(owner);
1898
+ child["#Load"] ||= /* @__PURE__ */ new Map();
1899
+ (pending ||= load()).then((mod) => {
1900
+ renderer = _content("", ...mod._)();
1901
+ queueAsyncRender(child, (child) => insertLoaded(renderer, child, owner[nodeAccessor], awaitCounter));
1902
+ }, loadFailed(child, awaitCounter));
1903
+ }
1904
+ };
1905
+ }
1906
+ function insertLoaded(renderer, branch, marker, awaitCounter) {
1907
+ const parent = marker.parentNode;
1908
+ branch["#Creating"] = 1;
1909
+ renderer["clone"](branch, parent.namespaceURI);
1910
+ setupBranch(renderer, branch);
1911
+ applyLoad(branch, () => {
1912
+ insertBranchBefore(branch, parent, marker);
1913
+ marker.remove();
1914
+ pendingScopes.push(branch);
1915
+ awaitCounter?.c();
1916
+ });
1917
+ }
1918
+ function loadFailed(scope, awaitCounter) {
1919
+ return (error) => {
1920
+ if (awaitCounter) awaitCounter.i = 0;
1921
+ queueAsyncRender(scope, renderCatch, error);
1922
+ };
1923
+ }
1924
+ function applyLoad(scope, insert) {
1925
+ const values = scope["#Load"];
1926
+ let remaining;
1927
+ scope["#Load"] = 0;
1928
+ if (remaining = values?.size) for (const [promise, entry] of values) promise.then((signal) => {
1929
+ entry["signal"] = signal;
1930
+ if (!--remaining) {
1931
+ scope["#Creating"] = 1;
1932
+ pendingScopes.push(scope);
1933
+ queueAsyncRender(scope, (scope) => {
1934
+ values.forEach((e) => e["signal"]._(scope, e["value"]));
1935
+ insert();
1936
+ });
1937
+ }
1938
+ }, () => 0);
1939
+ else insert();
1940
+ }
1941
+ function _load_signal(load) {
1942
+ let pending;
1943
+ let signal;
1944
+ return (scope, value) => {
1945
+ pending ||= load();
1946
+ if (scope["#Load"] || !("#Load" in scope) && scope["#Creating"]) (scope["#Load"] ||= /* @__PURE__ */ new Map()).set(pending, { ["value"]: value });
1947
+ else if (signal) signal(scope, value);
1948
+ else pending.then((mod) => queueAsyncRender(scope, signal = mod._, value), () => 0);
1949
+ };
1950
+ }
1951
+ function _load_visible_trigger(selector, options) {
1952
+ let pending;
1953
+ let el;
1954
+ return (load) => () => (pending ||= new Promise((resolve) => (el = getSelectorOrResolve(selector, resolve)) && new IntersectionObserver((entries, io) => entries.some((entry) => entry.isIntersecting) && resolve(io.disconnect()), options).observe(el))).then(load);
1955
+ }
1956
+ function _load_idle_trigger(options) {
1957
+ let pending;
1958
+ return (load) => () => (pending ||= new Promise((resolve) => (self.requestIdleCallback || resolve)(resolve, options))).then(load);
1959
+ }
1960
+ function _load_event_trigger(event, selector) {
1961
+ let pending;
1962
+ return (load) => () => (pending ||= new Promise((resolve) => getSelectorOrResolve(selector, resolve)?.addEventListener(event, resolve, { once: true }))).then(load);
1963
+ }
1964
+ function _load_media_trigger(query) {
1965
+ let pending;
1966
+ let mql;
1967
+ return (load) => () => (pending ||= new Promise((resolve) => (mql = matchMedia(query)).matches ? resolve() : mql.addEventListener("change", resolve, { once: true }))).then(load);
1968
+ }
1969
+ function _load_race_trigger(...triggers) {
1970
+ const noop = () => Promise.resolve();
1971
+ let pending;
1972
+ return (load) => () => (pending ||= Promise.race(triggers.map((t) => t(noop)()))).then(load);
1973
+ }
1974
+ function getSelectorOrResolve(selector, resolve) {
1975
+ return document.querySelector(selector) || (console.warn(`A lazy load trigger could not find an element matching "${selector}". The module was loaded immediately.`), resolve());
1976
+ }
1977
+ //#endregion
1795
1978
  exports.$signal = $signal;
1796
1979
  exports.$signalReset = $signalReset;
1797
1980
  exports._assert_hoist = _assert_hoist;
@@ -1862,7 +2045,16 @@ exports._id = _id;
1862
2045
  exports._if = _if;
1863
2046
  exports._if_closure = _if_closure;
1864
2047
  exports._let = _let;
2048
+ exports._let_change = _let_change;
1865
2049
  exports._lifecycle = _lifecycle;
2050
+ exports._load_event_trigger = _load_event_trigger;
2051
+ exports._load_idle_trigger = _load_idle_trigger;
2052
+ exports._load_media_trigger = _load_media_trigger;
2053
+ exports._load_race_trigger = _load_race_trigger;
2054
+ exports._load_setup = _load_setup;
2055
+ exports._load_signal = _load_signal;
2056
+ exports._load_template = _load_template;
2057
+ exports._load_visible_trigger = _load_visible_trigger;
1866
2058
  exports._on = _on;
1867
2059
  exports._or = _or;
1868
2060
  exports._resume = _resume;
@@ -1887,4 +2079,5 @@ exports.forTo = forTo;
1887
2079
  exports.forUntil = forUntil;
1888
2080
  exports.init = init;
1889
2081
  exports.initEmbedded = initEmbedded;
2082
+ exports.ready = ready;
1890
2083
  exports.run = run;