@markless/bundler 0.5.0 → 0.6.0

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.
@@ -3,6 +3,8 @@ import { joinURL } from "ufo";
3
3
  const MARKLESS_DEV_ERROR_EVENT = "markless:dev-error";
4
4
  const MARKLESS_DEV_ERROR_CLEAR_EVENT = "markless:dev-error-clear";
5
5
  const MARKLESS_DEV_ERROR_CLIENT_ID = "virtual:markless:dev-error-client";
6
+ const MARKLESS_DEV_RELOADS_EVENT = "markless:dev-reloads";
7
+ const MARKLESS_DEV_RELOADS_ATTRIBUTE = "data-markless-dev-reloads";
6
8
  const PLUGIN_CODE_KIND = "markless-dev-error";
7
9
  const PLUGIN_CODE_VERSION = 1;
8
10
  var MarklessCompileError = class extends Error {
@@ -171,4 +173,4 @@ const documentStyles = `
171
173
  .panel{width:min(60rem,100%);padding:clamp(1.25rem,3vw,2.5rem);border:1px solid color-mix(in srgb,CanvasText 20%,transparent);border-top:4px solid #c9362b;border-radius:.5rem;background:Canvas;box-shadow:0 1rem 3rem #0002}
172
174
  header{display:flex;flex-direction:column;gap:.6rem;margin-bottom:1rem}.badge{align-self:flex-start;padding:.15rem .45rem;border-radius:.25rem;background:color-mix(in srgb,#c9362b 14%,Canvas);color:#c9362b;font:600 .75rem ui-monospace,monospace}h1{margin:0;font-size:clamp(1.4rem,3vw,2rem);line-height:1.2}h2{margin:1rem 0 .25rem;font-size:.8rem;text-transform:uppercase;letter-spacing:.06em;color:color-mix(in srgb,CanvasText 65%,transparent)}p{margin:.3rem 0 1rem;line-height:1.55}a{color:LinkText}.location{display:inline-block;margin-bottom:.5rem;font:500 .9rem ui-monospace,monospace}.frame,details pre{overflow:auto;padding:1rem;border-radius:.35rem;background:color-mix(in srgb,CanvasText 7%,Canvas);font: .85rem/1.55 ui-monospace,monospace;white-space:pre}details{margin-top:1rem;border-top:1px solid color-mix(in srgb,CanvasText 15%,transparent);padding-top:1rem}summary{cursor:pointer;font-weight:600}.recovery{margin:1.5rem 0 0;color:color-mix(in srgb,CanvasText 65%,transparent);font-size:.9rem}`;
173
175
  //#endregion
174
- export { createCompileErrorPayload as a, renderMarklessDevErrorDocument as c, MarklessCompileError as i, renderMarklessDevErrorPlainText as l, MARKLESS_DEV_ERROR_CLIENT_ID as n, formatMarklessSourceFrame as o, MARKLESS_DEV_ERROR_EVENT as r, normalizeMarklessDevError as s, MARKLESS_DEV_ERROR_CLEAR_EVENT as t, serializeMarklessDevError as u };
176
+ export { MARKLESS_DEV_RELOADS_EVENT as a, formatMarklessSourceFrame as c, renderMarklessDevErrorPlainText as d, serializeMarklessDevError as f, MARKLESS_DEV_RELOADS_ATTRIBUTE as i, normalizeMarklessDevError as l, MARKLESS_DEV_ERROR_CLIENT_ID as n, MarklessCompileError as o, MARKLESS_DEV_ERROR_EVENT as r, createCompileErrorPayload as s, MARKLESS_DEV_ERROR_CLEAR_EVENT as t, renderMarklessDevErrorDocument as u };
@@ -3,6 +3,8 @@ import { CompilerDiagnostic, SourceSpan } from "@markless/compiler";
3
3
  export declare const MARKLESS_DEV_ERROR_EVENT = "markless:dev-error";
4
4
  export declare const MARKLESS_DEV_ERROR_CLEAR_EVENT = "markless:dev-error-clear";
5
5
  export declare const MARKLESS_DEV_ERROR_CLIENT_ID = "virtual:markless:dev-error-client";
6
+ export declare const MARKLESS_DEV_RELOADS_EVENT = "markless:dev-reloads";
7
+ export declare const MARKLESS_DEV_RELOADS_ATTRIBUTE = "data-markless-dev-reloads";
6
8
  export interface MarklessDevDiagnostic {
7
9
  readonly code: string;
8
10
  readonly message: string;
package/dist/dev-error.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as createCompileErrorPayload, c as renderMarklessDevErrorDocument, i as MarklessCompileError, l as renderMarklessDevErrorPlainText, n as MARKLESS_DEV_ERROR_CLIENT_ID, o as formatMarklessSourceFrame, r as MARKLESS_DEV_ERROR_EVENT, s as normalizeMarklessDevError, t as MARKLESS_DEV_ERROR_CLEAR_EVENT, u as serializeMarklessDevError } from "./dev-error-DRvO28Fd.js";
2
- export { MARKLESS_DEV_ERROR_CLEAR_EVENT, MARKLESS_DEV_ERROR_CLIENT_ID, MARKLESS_DEV_ERROR_EVENT, MarklessCompileError, createCompileErrorPayload, formatMarklessSourceFrame, normalizeMarklessDevError, renderMarklessDevErrorDocument, renderMarklessDevErrorPlainText, serializeMarklessDevError };
1
+ import { a as MARKLESS_DEV_RELOADS_EVENT, c as formatMarklessSourceFrame, d as renderMarklessDevErrorPlainText, f as serializeMarklessDevError, i as MARKLESS_DEV_RELOADS_ATTRIBUTE, l as normalizeMarklessDevError, n as MARKLESS_DEV_ERROR_CLIENT_ID, o as MarklessCompileError, r as MARKLESS_DEV_ERROR_EVENT, s as createCompileErrorPayload, t as MARKLESS_DEV_ERROR_CLEAR_EVENT, u as renderMarklessDevErrorDocument } from "./dev-error-2hi-Icjn.js";
2
+ export { MARKLESS_DEV_ERROR_CLEAR_EVENT, MARKLESS_DEV_ERROR_CLIENT_ID, MARKLESS_DEV_ERROR_EVENT, MARKLESS_DEV_RELOADS_ATTRIBUTE, MARKLESS_DEV_RELOADS_EVENT, MarklessCompileError, createCompileErrorPayload, formatMarklessSourceFrame, normalizeMarklessDevError, renderMarklessDevErrorDocument, renderMarklessDevErrorPlainText, serializeMarklessDevError };
@@ -1,4 +1,4 @@
1
- import "./types-BqSoEVp6.js";
1
+ import "./types-iOUoceJ-.js";
2
2
  import "@markless/serializer";
3
3
  import "@markless/compiler";
4
4
  import "@markless/web/inline/resumer";
package/dist/preload.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { o as MarklessBundleGraph } from "./types-BqSoEVp6.js";
2
- import { i as prerenderWakeVirtualModuleSourceFile, o as symbolVirtualModuleSourceFile, t as isExecutionLogChunk } from "./execution-log-D9cex1i1.js";
1
+ import { o as MarklessBundleGraph } from "./types-iOUoceJ-.js";
2
+ import { i as prerenderWakeVirtualModuleSourceFile, o as symbolVirtualModuleSourceFile, t as isExecutionLogChunk } from "./execution-log-BL-7a77M.js";
3
3
  import { UserConfig } from "vite";
4
4
  //#region src/build/preload-plan.d.ts
5
5
  type ModulePreloadPlanInput = {
@@ -89,10 +89,15 @@ export declare function isResumeSourceRequest(id: string): boolean;
89
89
  export declare function isRenderDataSourceRequest(id: string): boolean;
90
90
  export declare function isRouteNavigationSourceRequest(id: string): boolean;
91
91
  export declare function isClientPrimarySourceRequest(id: string): boolean;
92
+ export declare function resolverVirtualModuleSourceFile(id: string): string | null;
92
93
  //#endregion
93
94
  //#region src/build/planned-landing.d.ts
94
95
  export declare function plannedLandingFiles(bundle: Readonly<Record<string, unknown>>): Map<string, ReadonlySet<string>> | undefined;
95
96
  //#endregion
97
+ //#region src/build/warm-packs.d.ts
98
+ /** The packs a chunk evaluates a task after it runs, read from `warmPacksSuffix` before or after minifying. */
99
+ export declare function warmEvaluatedImports(code: string): string[];
100
+ //#endregion
96
101
  //#region src/build/route-pack-groups.d.ts
97
102
  export declare const MARKLESS_DEFERRED_PACK = "markless-deferred";
98
103
  export declare const MARKLESS_NAVIGATION_PACK_PREFIX = "navigation:";
package/dist/preload.js CHANGED
@@ -1,4 +1,4 @@
1
- import { At as isExecutionLogChunk, E as isRouteNavigationSourceRequest, Nt as planModulePreloadUrls, O as isSymbolOnlySourceRequest, Pt as planModulePreloads, T as isResumeSourceRequest, b as isClientPrimarySourceRequest, d as plannedLandingFiles, i as isMarklessNavigationPack, l as startupPackOfLazy, mt as prerenderWakeVirtualModuleSourceFile, n as MARKLESS_NAVIGATION_PACK_PREFIX, o as lazyStartupPackName, r as isMarklessDeferredPack, s as marklessDeferredChunkFileNames, t as MARKLESS_DEFERRED_PACK, w as isRenderDataSourceRequest, xt as symbolVirtualModuleSourceFile } from "./route-pack-groups-BpefyjrE.js";
1
+ import { A as isSymbolOnlySourceRequest, D as isResumeSourceRequest, E as isRenderDataSourceRequest, I as resolverVirtualModuleSourceFile, It as planModulePreloadUrls, Lt as planModulePreloads, Nt as isExecutionLogChunk, O as isRouteNavigationSourceRequest, S as isClientPrimarySourceRequest, _t as prerenderWakeVirtualModuleSourceFile, i as isMarklessNavigationPack, l as startupPackOfLazy, n as MARKLESS_NAVIGATION_PACK_PREFIX, o as lazyStartupPackName, p as plannedLandingFiles, r as isMarklessDeferredPack, s as marklessDeferredChunkFileNames, t as MARKLESS_DEFERRED_PACK, u as warmEvaluatedImports, wt as symbolVirtualModuleSourceFile } from "./route-pack-groups-BXc755qH.js";
2
2
  import { r as optimizedDepsToInclude } from "./optimized-deps-BfzxSm6C.js";
3
3
  //#region src/build/module-preload-dom.ts
4
4
  const PRIORITY_RANK = {
@@ -73,4 +73,4 @@ function rememberHref(seen, href, baseURI) {
73
73
  if (baseURI) seen.add(new URL(href, baseURI).href);
74
74
  }
75
75
  //#endregion
76
- export { MARKLESS_DEFERRED_PACK, MARKLESS_NAVIGATION_PACK_PREFIX, isClientPrimarySourceRequest, isExecutionLogChunk, isMarklessDeferredPack, isMarklessNavigationPack, isRenderDataSourceRequest, isResumeSourceRequest, isRouteNavigationSourceRequest, isSymbolOnlySourceRequest, lazyStartupPackName, marklessDeferredChunkFileNames, optimizedDepsToInclude, planModulePreloadUrls, planModulePreloads, plannedLandingFiles, preloadLazySymbolModules, prerenderWakeVirtualModuleSourceFile, startupPackOfLazy, symbolVirtualModuleSourceFile };
76
+ export { MARKLESS_DEFERRED_PACK, MARKLESS_NAVIGATION_PACK_PREFIX, isClientPrimarySourceRequest, isExecutionLogChunk, isMarklessDeferredPack, isMarklessNavigationPack, isRenderDataSourceRequest, isResumeSourceRequest, isRouteNavigationSourceRequest, isSymbolOnlySourceRequest, lazyStartupPackName, marklessDeferredChunkFileNames, optimizedDepsToInclude, planModulePreloadUrls, planModulePreloads, plannedLandingFiles, preloadLazySymbolModules, prerenderWakeVirtualModuleSourceFile, resolverVirtualModuleSourceFile, startupPackOfLazy, symbolVirtualModuleSourceFile, warmEvaluatedImports };
@@ -1,13 +1,13 @@
1
- import { a as createCompileErrorPayload, i as MarklessCompileError } from "./dev-error-DRvO28Fd.js";
2
- import { $ as MARKLESS_EXECUTION_DEMAND, A as normalizeVirtualId$2, B as sourceForSymbolVirtualImporter, C as isRelativeImport, Ct as EXECUTION_LOG_DISPATCH_MODULE_IDS, D as isScalarPlanSourceRequest, Dt as executionLogVirtualModuleSource, E as isRouteNavigationSourceRequest, Et as executionLogActivationInjection, F as serverSharedSourceRequest, G as emitPrerenderTriggerGroupModule, H as stripBuildPrefix, I as sharedReachedRenderDataRequest, J as adaptImportedCaptureResolver, K as planPrerenderTriggerGroups, L as sourceForPrerenderWakeVirtualImporter, M as renderDataReachedFromQuery, Mt as requalifyExecutionLogModuleHook, N as resolveVirtualId, O as isSymbolOnlySourceRequest, Ot as hasExecutionLogModuleHook, P as resolverVirtualModuleSourceFile, Pt as planModulePreloads, Q as MARKLESS_BYTE_ATTRIBUTION, R as sourceForResumeVirtualImporter, S as isPrerenderWakeSourceRequest, St as withoutFirstUse, T as isResumeSourceRequest, Tt as MARKLESS_EXECUTION_LOG_MODULE_ID, U as virtualModuleSourceForLoad, V as sourceForTriggerGroupVirtualImporter, W as emitPrerenderBoundaryRendererModule, X as MARKLESS_BUILD_PREFIX, Z as MARKLESS_BUNDLE_GRAPH, _ as devBrowserVirtualModuleUrl, _t as scopedSymbolExportName, a as isStartupPack, b as isClientPrimarySourceRequest, bt as symbolVirtualModuleId, c as planRoutePackGroups, ct as emitResumeModule, dt as encodedSymbolSource, et as MARKLESS_EXECUTION_SIZES, f as MARKLESS_ROUTE_SOURCE_QUERY_RE, ft as payloadModule, g as devBrowserSourceModuleUrl, gt as rewriteSymbolModuleExport, h as clientSymbolEntries, ht as resumeVirtualModuleId, j as pathname$1, jt as normalizeExecutionLogMode, k as materializedReachedRenderDataSource, kt as injectExecutionLogModuleHook, l as startupPackOfLazy, lt as emitSettleModule, m as clientRouteArtifactReference, nt as outputDefaults, ot as demandsOverlay, p as TSRX_SOURCE_FILE$1, pt as prerenderWakeVirtualModuleId, q as triggerGroupVirtualModuleId, rt as MARKLESS_VIRTUAL_PREFIX, s as marklessDeferredChunkFileNames, st as emitOverlayLoaderInstall, tt as MARKLESS_INTERACTION_CLOSURES, u as MARKLESS_INTERACTION_CLOSURES_ASSET, ut as emitSourceModule, v as emittedBundleModuleIds, vt as settleVirtualModuleId, w as isRenderDataSourceRequest, wt as MARKLESS_EXECUTION_LOG_GLOBAL, x as isMarklessRuntimeModule, xt as symbolVirtualModuleSourceFile, y as executionLogRuntimeModuleId, yt as symbolEntryVirtualModuleId, z as sourceForSettleVirtualImporter } from "./route-pack-groups-BpefyjrE.js";
1
+ import { o as MarklessCompileError, s as createCompileErrorPayload } from "./dev-error-2hi-Icjn.js";
2
+ import { $ as MARKLESS_BUNDLE_GRAPH, A as isSymbolOnlySourceRequest, At as executionLogVirtualModuleSource, B as sourceForResumeVirtualImporter, C as isMarklessRuntimeModule, Ct as symbolVirtualModuleId, D as isResumeSourceRequest, Dt as MARKLESS_EXECUTION_LOG_GLOBAL, E as isRenderDataSourceRequest, Et as EXECUTION_LOG_DISPATCH_MODULE_IDS, F as resolveVirtualId, Ft as requalifyExecutionLogModuleHook, G as virtualModuleSourceForLoad, H as sourceForSymbolVirtualImporter, I as resolverVirtualModuleSourceFile, J as planPrerenderTriggerGroups, K as emitPrerenderBoundaryRendererModule, L as serverSharedSourceRequest, Lt as planModulePreloads, M as normalizeVirtualId$2, Mt as injectExecutionLogModuleHook, N as pathname$1, O as isRouteNavigationSourceRequest, Ot as MARKLESS_EXECUTION_LOG_MODULE_ID, P as renderDataReachedFromQuery, Pt as normalizeExecutionLogMode, Q as MARKLESS_BUILD_PREFIX, R as sharedReachedRenderDataRequest, S as isClientPrimarySourceRequest, St as symbolEntryVirtualModuleId, T as isRelativeImport, Tt as withoutFirstUse, U as sourceForTriggerGroupVirtualImporter, V as sourceForSettleVirtualImporter, W as stripBuildPrefix, X as adaptImportedCaptureResolver, Y as triggerGroupVirtualModuleId, Z as MARKLESS_BUILD_METADATA_FILES, _ as clientSymbolEntries, a as isStartupPack, at as outputDefaults, b as emittedBundleModuleIds, bt as scopedSymbolExportName, c as planRoutePackGroups, d as warmPacksSuffix, dt as emitResumeModule, et as MARKLESS_BYTE_ATTRIBUTION, f as MARKLESS_INTERACTION_CLOSURES_ASSET, ft as emitSettleModule, g as clientRouteArtifactReference, gt as prerenderWakeVirtualModuleId, h as TSRX_SOURCE_FILE$1, ht as payloadModule, it as MARKLESS_PUBLIC_BUILD_METADATA_FILES, j as materializedReachedRenderDataSource, jt as hasExecutionLogModuleHook, k as isScalarPlanSourceRequest, kt as executionLogActivationInjection, l as startupPackOfLazy, lt as demandsOverlay, m as MARKLESS_ROUTE_SOURCE_QUERY_RE, mt as encodedSymbolSource, nt as MARKLESS_EXECUTION_SIZES, ot as MARKLESS_VIRTUAL_PREFIX, pt as emitSourceModule, q as emitPrerenderTriggerGroupModule, rt as MARKLESS_INTERACTION_CLOSURES, s as marklessDeferredChunkFileNames, tt as MARKLESS_EXECUTION_DEMAND, ut as emitOverlayLoaderInstall, v as devBrowserSourceModuleUrl, vt as resumeVirtualModuleId, w as isPrerenderWakeSourceRequest, wt as symbolVirtualModuleSourceFile, x as executionLogRuntimeModuleId, xt as settleVirtualModuleId, y as devBrowserVirtualModuleUrl, yt as rewriteSymbolModuleExport, z as sourceForPrerenderWakeVirtualImporter } from "./route-pack-groups-BXc755qH.js";
3
3
  import { joinURL, parsePath, withLeadingSlash, withQuery, withoutLeadingSlash } from "ufo";
4
4
  import { PROTOCOL_EVENT_ACTION_KIND, PROTOCOL_IDLE_EVENT_NAME, createStorageSeedMetadataFromGraphNodeId, jsonSourceWithNonFiniteNumbers } from "@markless/serializer";
5
5
  import { existsSync, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
6
- import { basename, dirname, isAbsolute, join, normalize, relative, resolve } from "pathe";
7
- import { DEBUGGING_PLAYBOOK_HINT, LEAN_DISPATCH_MARKER_MODULES, RUNTIME_CAPABILITY_MODULE_IDS, artifactChildCandidates, callsImportedOrFreeName, collectTsrxModuleDiagnostics, compileTsrxModule, compileTsrxModuleLinkArtifact, componentEdgeSymbolRoutes, computeExecutionAttribution, computeLinkedInterfaces, delegateChildRenderPlan, delegateChildRendering, delegateChildResolutionRequests, delegateMaterializationScope, emitSymbolResolverModule, evaluateModuleConstants, importedRowComponentMints, importedRowSlotReaders, importedSymbolRoutes, linkBarrelComponents, linkClaimManifests, linkDelegateChildren, linkImportedModules, linkedChildrenHaveBrowserTriggers, linkedImportedClaimsMissing, linkedImportedSymbolInputs, linkedManifestHasBrowserTriggers, linkedModuleChildDiagnostics, linkedModuleChildKey, linkedModuleClaimPlan, linkedModuleImportRequests, linkedModuleLoadSource, linkedRenderDataBoundarySymbols, linkedRenderDataOnlyChange, linkedRenderDataReachRoot, linkedResolverClaimVerdict, linkedRouteArtifactRegistration, linkedSymbolRouteRequests, moduleInterfaceHash, moduleLinkResolutionKey, overlayBarrelInterfaces, parseJavaScriptModule, planDelegateChildren, planEmittedClaimOwnership, planLinkedModuleChildren, planRenderDataModule, planTransformRequest, prerenderInterfacesComplete, renderDataClaimManifest, renderDataReachImportSources, uniqueLinkedModuleChildren } from "@markless/compiler";
6
+ import { basename, dirname, extname, isAbsolute, join, normalize, relative, resolve } from "pathe";
7
+ import { DEBUGGING_PLAYBOOK_HINT, LEAN_DISPATCH_MARKER_MODULES, RUNTIME_CAPABILITY_MODULE_IDS, artifactChildCandidates, callsImportedOrFreeName, collectTsrxModuleDiagnostics, compileTsrxModule, compileTsrxModuleLinkArtifact, componentEdgeSymbolRoutes, computeExecutionAttribution, computeLinkedInterfaces, delegateChildRenderPlan, delegateChildRendering, delegateChildResolutionRequests, delegateMaterializationScope, emitSymbolResolverModule, evaluateModuleConstants, importedNestedRepeats, importedRowComponentMints, importedRowSlotReaders, importedRowTemplateMints, importedSymbolRoutes, linkBarrelComponents, linkClaimManifests, linkDelegateChildren, linkImportedModules, linkedChildrenHaveBrowserTriggers, linkedImportedClaimsMissing, linkedImportedSymbolInputs, linkedManifestHasBrowserTriggers, linkedModuleChildDiagnostics, linkedModuleChildKey, linkedModuleClaimPlan, linkedModuleImportRequests, linkedModuleLoadSource, linkedRenderDataBoundarySymbols, linkedRenderDataOnlyChange, linkedRenderDataReachRoot, linkedResolverClaimVerdict, linkedRouteArtifactRegistration, linkedSymbolRouteRequests, moduleInterfaceHash, moduleLinkResolutionKey, overlayBarrelInterfaces, parseJavaScriptModule, planDelegateChildren, planEmittedClaimOwnership, planLinkedModuleChildren, planRenderDataModule, planTransformRequest, prerenderInterfacesComplete, renderDataClaimManifest, renderDataReachImportSources, uniqueLinkedModuleChildren } from "@markless/compiler";
8
8
  import { PRERENDER_INLINE_EVENT_NAMES_TOKEN, createInlineResumerDebugRegistrationSource, createInlineResumerSelfWakeSource, createInlineResumerSource, createPrerenderInlineResumerSource, createPrerenderSettleInlineResumerSource } from "@markless/web/inline/resumer";
9
9
  import { parse, parseSync } from "rolldown/experimental";
10
- import { mkdir, readFile, rename, rm, rmdir } from "node:fs/promises";
10
+ import { copyFile, mkdir, readFile, readdir, rename, rm, rmdir } from "node:fs/promises";
11
11
  import { defDGraph } from "@thi.ng/dgraph";
12
12
  import { RolldownMagicString } from "rolldown";
13
13
  import { isAbsolute as isAbsolute$1 } from "node:path";
@@ -594,6 +594,10 @@ const PROTOCOL_IDLE_EVENT_NAME$1 = "idle";
594
594
  */
595
595
  const PROTOCOL_LOCATOR_PATHS_ATTRIBUTE = "data-markless-paths";
596
596
  //#endregion
597
+ //#region ../serializer/src/protocol-page-markers.ts
598
+ const PROTOCOL_CONTAINER_START_COMMENT = "markless:page-start";
599
+ const PROTOCOL_CONTAINER_END_COMMENT = "markless:page-end";
600
+ //#endregion
597
601
  //#region ../web/src/inline/defer.ts
598
602
  /**
599
603
  * The one startup helper deferred triggers share. Serialized whole into a served
@@ -601,12 +605,20 @@ const PROTOCOL_LOCATOR_PATHS_ATTRIBUTE = "data-markless-paths";
601
605
  * from compiler-emitted DOM-order indexes, index 0 being the container itself,
602
606
  * which hands records the runtime owns (arms, rows) to the runtime.
603
607
  */
604
- function createMarklessDefer(loadModule, pathsAttribute) {
608
+ function createMarklessDefer(loadModule, pageStart, pageEnd, pathsAttribute) {
605
609
  const scope = globalThis;
606
610
  const clockOf = (root) => root.__mClock || {
607
611
  frame: (run) => requestAnimationFrame(run),
608
612
  idle: (run) => scope.scheduler?.postTask ? scope.scheduler.postTask(run, { priority: "background" }) : typeof requestIdleCallback === "function" ? requestIdleCallback(run, { timeout: 2e3 }) : setTimeout(run, 200)
609
613
  };
614
+ const census = (root) => {
615
+ const live = [root];
616
+ const walker = document.createTreeWalker(root, 129);
617
+ for (let next = walker.nextNode(); next; next = walker.nextNode()) if (next.nodeType !== 8) live.push(next);
618
+ else if (next.data === pageStart) live.length = 1;
619
+ else if (next.data === pageEnd) break;
620
+ return live;
621
+ };
610
622
  const idle = (root, run) => {
611
623
  const clock = clockOf(root);
612
624
  const next = () => clock.idle(() => root.__marklessArmRegistering?.size ? next() : run());
@@ -627,7 +639,8 @@ function createMarklessDefer(loadModule, pathsAttribute) {
627
639
  root,
628
640
  event: {
629
641
  type: eventName,
630
- target: host
642
+ target: host,
643
+ bubbles: false
631
644
  },
632
645
  element: host
633
646
  };
@@ -635,20 +648,20 @@ function createMarklessDefer(loadModule, pathsAttribute) {
635
648
  if (!queue && root.__marklessDelegatedDispatch === true) return idle(root, () => claim(host));
636
649
  claimed.add(host);
637
650
  if (lane !== "visible") fired.add(host);
638
- root.__marklessCensus ||= [root, ...root.getElementsByTagName("*")];
651
+ root.__marklessCensus ||= census(root);
639
652
  root.__marklessDelegatedDispatch ||= eventName;
640
653
  pending++;
641
- (queue ? Promise.resolve(queue(input)) : loadModule(url).then((module) => module.resumeContainerEvent(input))).then(() => {
654
+ (queue ? Promise.resolve(queue(input)) : (root.__mResume ||= loadModule(url)).then((module) => module.resumeContainerEvent(input))).then(() => {
642
655
  if (root.__asyncResumeRuntimeStarted) return;
643
656
  fired.add(host);
644
657
  if (!--pending && root.__marklessDelegatedDispatch === eventName) root.__marklessDelegatedDispatch = void 0;
645
658
  });
646
659
  };
647
- const all = root.getElementsByTagName("*");
660
+ const all = root.__marklessCensus ?? census(root);
648
661
  const paths = pathsAttribute && root.getAttribute?.(pathsAttribute);
649
- if (paths && parseInt(paths) !== all.length + 1) root.__marklessShifted = 1;
662
+ if (paths && parseInt(paths) !== all.length) root.__marklessShifted = 1;
650
663
  const hosts = root.__marklessShifted ? [root] : hostIndexes.flatMap((index) => {
651
- const host = index ? all[index - 1] : root;
664
+ const host = all[index];
652
665
  return host ? [host] : [];
653
666
  });
654
667
  if (lane === "idle") return idle(root, () => hosts.forEach(claim));
@@ -665,7 +678,7 @@ function createMarklessDefer(loadModule, pathsAttribute) {
665
678
  const INLINE_DEFER_LOADER_SOURCE = "(url) => import(/* @vite-ignore */ url)";
666
679
  /** An expression that installs the helper once per document and evaluates to it; a build passes the factory minified. */
667
680
  function inlineDeferSource(factory = createMarklessDefer.toString()) {
668
- return `(globalThis.__mDefer||=(${factory})(${INLINE_DEFER_LOADER_SOURCE},${JSON.stringify(PROTOCOL_LOCATOR_PATHS_ATTRIBUTE)}))`;
681
+ return `(globalThis.__mDefer||=(${factory})(${INLINE_DEFER_LOADER_SOURCE},${JSON.stringify(PROTOCOL_CONTAINER_START_COMMENT)},${JSON.stringify(PROTOCOL_CONTAINER_END_COMMENT)},${JSON.stringify(PROTOCOL_LOCATOR_PATHS_ATTRIBUTE)}))`;
669
682
  }
670
683
  /** One lane's registration, appended only to a served page whose records name that lane's event. */
671
684
  function createInlineDeferTriggerSource(lane, hostIndexes) {
@@ -1058,6 +1071,7 @@ async function transformTsrxModuleWithPrerenderWakeClosure(input, linkedChildHas
1058
1071
  const styleCss = compiled.publicRenderPlan.styleScopes.map((scope) => scope.cssText).join("\n");
1059
1072
  const styleId = compiled.publicRenderPlan.styleScopes.length > 0 ? `${MARKLESS_VIRTUAL_PREFIX}style:${encodedModuleId}.css` : null;
1060
1073
  const rosterDerivation = compiled.moduleGraphInterface.render.components.some((component) => component.rosterDerivation === true);
1074
+ const storageCells = compiled.moduleGraphInterface.render.components.some((component) => component.storageCells === true);
1061
1075
  const prerenderClosureNeedsWake = needsFullResume(compiled.protocolState, compiled.protocolView, compiled.runtimeDemandMap) || input.prerenderRecords === true && linkedChildHasBrowserTriggers;
1062
1076
  const emitsPrerenderWakeVariant = input.prerenderWakeVariant === true && compiled.publicRenderModule.renderDataModuleSource !== void 0 && prerenderInterfacesComplete(compiled, input) && prerenderClosureNeedsWake;
1063
1077
  const emitsPrerenderWakeFacade = input.prerenderWakeFacade === true && input.prerenderWakeVariant === true && compiled.publicRenderModule.renderDataModuleSource !== void 0 && prerenderInterfacesComplete(compiled, input) && prerenderClosureNeedsWake;
@@ -1139,7 +1153,10 @@ async function transformTsrxModuleWithPrerenderWakeClosure(input, linkedChildHas
1139
1153
  renderDataId: canonicalRenderData && compiled.publicRenderModule.renderDataModuleSource ? renderDataId : void 0,
1140
1154
  linkedRowSlotReaders: importedRowSlotReaders(input.importedModuleInterfaces),
1141
1155
  linkedRowComponents: importedRowComponentMints(input.importedModuleInterfaces),
1156
+ linkedRowTemplates: importedRowTemplateMints(input.importedModuleInterfaces),
1157
+ linkedNestedRepeats: importedNestedRepeats(input.importedModuleInterfaces),
1142
1158
  rosterDerivation,
1159
+ storageCells,
1143
1160
  hasBoundSymbols: compiled.boundSymbolResolver.rows.length > 0,
1144
1161
  boundSymbolDescriptors,
1145
1162
  symbols: symbolRows,
@@ -1166,6 +1183,7 @@ async function transformTsrxModuleWithPrerenderWakeClosure(input, linkedChildHas
1166
1183
  moduleId: triggerGroupVirtualModuleId(input.filename, index)
1167
1184
  })),
1168
1185
  rosterDerivation,
1186
+ storageCells,
1169
1187
  installResumeSummary: true,
1170
1188
  recordsOnly: true,
1171
1189
  hasBoundSymbols: compiled.boundSymbolResolver.rows.length > 0,
@@ -1246,6 +1264,8 @@ async function transformTsrxModuleWithPrerenderWakeClosure(input, linkedChildHas
1246
1264
  environment: input.environment ?? "lib",
1247
1265
  linkedRowSlotReaders: importedRowSlotReaders(input.importedModuleInterfaces),
1248
1266
  linkedRowComponents: importedRowComponentMints(input.importedModuleInterfaces),
1267
+ linkedRowTemplates: importedRowTemplateMints(input.importedModuleInterfaces),
1268
+ linkedNestedRepeats: importedNestedRepeats(input.importedModuleInterfaces),
1249
1269
  clientOutput: input.clientOutput ?? "full",
1250
1270
  executionLog: input.executionLog,
1251
1271
  headInjections: headInjections.length > 0 ? headInjections : void 0,
@@ -1421,6 +1441,7 @@ async function compileWithBlockingDiagnostics(input, resolverId) {
1421
1441
  moduleId: input.moduleId,
1422
1442
  source: input.source,
1423
1443
  ...input.serverOnlyProps?.length ? { serverOnlyProps: input.serverOnlyProps } : {},
1444
+ ...input.routeRoot ? { routeRoot: true } : {},
1424
1445
  buildId: input.buildId,
1425
1446
  resolverId,
1426
1447
  symbols: input.symbols ?? [],
@@ -1507,6 +1528,7 @@ function withServedScalarDemand(map, served) {
1507
1528
  return {
1508
1529
  ...action,
1509
1530
  runtimeModuleIds: union(action.runtimeModuleIds, lean.runtimeModuleIds),
1531
+ ...lean.firstUse ? { firstUse: lean.firstUse } : {},
1510
1532
  ...lean.plan?.kind === "closure" ? { plan: lean.plan } : {}
1511
1533
  };
1512
1534
  })
@@ -2135,6 +2157,10 @@ function unmappedChunkSpecifiers(bundle) {
2135
2157
  function marklessBuildManifestDir(clientOutDir) {
2136
2158
  return join(dirname(clientOutDir), ".markless", basename(clientOutDir));
2137
2159
  }
2160
+ /** Where a build metadata file such as `build/bundle-graph.json` lands for a client output. */
2161
+ function marklessBuildManifestPath(clientOutDir, metadataFile) {
2162
+ return join(marklessBuildManifestDir(clientOutDir), basename(metadataFile));
2163
+ }
2138
2164
  /** The chunk import map a packed client build hands to the server that renders its documents. */
2139
2165
  function marklessImportMapPath(clientOutDir) {
2140
2166
  return join(marklessBuildManifestDir(clientOutDir), "import-map.json");
@@ -2148,6 +2174,17 @@ async function moveImportMapOutOfClientOutput(clientOutDir, emitted) {
2148
2174
  await rename(written, target);
2149
2175
  await rmdir(dirname(written)).catch(() => void 0);
2150
2176
  }
2177
+ async function moveBuildMetadataOutOfClientOutput(clientOutDir, emitted, options) {
2178
+ const served = new Set(options.executionLogActive ? MARKLESS_PUBLIC_BUILD_METADATA_FILES : []);
2179
+ for (const file of MARKLESS_BUILD_METADATA_FILES) {
2180
+ const target = marklessBuildManifestPath(clientOutDir, file);
2181
+ await rm(target, { force: true });
2182
+ if (!emitted.has(file)) continue;
2183
+ const written = join(clientOutDir, file);
2184
+ await mkdir(dirname(target), { recursive: true });
2185
+ await (served.has(file) ? copyFile(written, target) : rename(written, target));
2186
+ }
2187
+ }
2151
2188
  //#endregion
2152
2189
  //#region src/build/bundle-graph.ts
2153
2190
  const SLOW_BUNDLE_TOTAL = 19200;
@@ -2768,7 +2805,7 @@ function collapseLazyModuleFacades(bundle, onEdit, options = {}) {
2768
2805
  eagerImports.set(evaluator.fileName, [...eagerImports.get(evaluator.fileName) ?? [], target]);
2769
2806
  }
2770
2807
  }
2771
- for (const [fileName, loaders] of registered) additions.get(fileName).push(`(globalThis.${PACK_REGISTRY}??={})[import.meta.url]={${[...loaders].join(",")}};`);
2808
+ for (const [fileName, loaders] of registered) additions.get(fileName).push(`${PACK_REGISTRATION}={${[...loaders].join(",")}};`);
2772
2809
  for (const chunk of chunks.values()) {
2773
2810
  if (facades.has(chunk.fileName)) continue;
2774
2811
  const replacements = [];
@@ -2800,10 +2837,10 @@ function collapseLazyModuleFacades(bundle, onEdit, options = {}) {
2800
2837
  }),
2801
2838
  ...additions.get(chunk.fileName) ?? [],
2802
2839
  ...lookup && replacements.some(({ source }) => source.startsWith("__marklessPackLoad")) ? [PACK_LOAD_SOURCE] : [],
2803
- ...evaluated.size ? [`setTimeout(()=>{for(const pack of[${[...evaluated].map((target) => {
2840
+ ...evaluated.size ? [warmPacksSuffix([...evaluated].map((target) => {
2804
2841
  const path = relative(dirname(chunk.fileName), target.fileName);
2805
- return `import(${JSON.stringify(path.startsWith(".") ? path : `./${path}`)})`;
2806
- }).join(",")}])pack.catch(()=>{})});`] : []
2842
+ return path.startsWith(".") ? path : `./${path}`;
2843
+ }))] : []
2807
2844
  ].join("\n");
2808
2845
  if (replacements.length || suffix) onEdit?.(chunk, replacements, suffix);
2809
2846
  const pieces = [];
@@ -2823,6 +2860,7 @@ function collapseLazyModuleFacades(bundle, onEdit, options = {}) {
2823
2860
  return { removed: [...facades.keys()] };
2824
2861
  }
2825
2862
  const PACK_REGISTRY = "__marklessPacks";
2863
+ const PACK_REGISTRATION = `(globalThis.${PACK_REGISTRY}??={})[import.meta.url]`;
2826
2864
  const PACKED_NAME_PATTERN = /\$ml[\w$]*|__marklessNamespace[\w$]*/g;
2827
2865
  const PACK_LOAD = "__marklessPackLoad";
2828
2866
  const PACK_LOAD_SOURCE = `function ${PACK_LOAD}(specifier,loader,load){const pack=globalThis.${PACK_REGISTRY}?.[import.meta.resolve?.(specifier)];return pack?Promise.resolve().then(pack[loader]):load().then(module=>module[loader]())}`;
@@ -3679,6 +3717,9 @@ const RUNS_WITHOUT_INPUT = {
3679
3717
  overlay: true
3680
3718
  };
3681
3719
  const LEAN_DISPATCH_MODULE_IDS = new Set(Object.values(LEAN_DISPATCH_MARKER_MODULES).flat());
3720
+ function isLeanAction(runtimeModuleIds) {
3721
+ return [...runtimeModuleIds].some((id) => LEAN_DISPATCH_MODULE_IDS.has(id));
3722
+ }
3682
3723
  function computeInteractionClosures(input) {
3683
3724
  const { modules } = input;
3684
3725
  const sources = [...input.demand];
@@ -3793,10 +3834,14 @@ function computeInteractionClosures(input) {
3793
3834
  };
3794
3835
  for (const file of files) for (const symbolId of demand.get(file).landingSymbols) seedSymbol(file, symbolId);
3795
3836
  if (resume !== "unknown") for (const [owner, symbolIds] of resume.symbols) for (const symbolId of symbolIds) seedSymbol(owner, symbolId);
3837
+ const bootBound = resume !== "unknown" && [...files].every((file) => {
3838
+ const merged = demand.get(file);
3839
+ return merged.landingSymbols.size === 0 && merged.landingRuntimeModuleIds.size === 0 && [...merged.actions.values()].every((action) => isLeanAction(action.runtimeModuleIds) && !(action.lean ?? action).unknown);
3840
+ }) ? { runtimeIds: new Set(resume.runtimeModuleIds) } : {};
3796
3841
  const consumers = [{
3797
3842
  key: "boot",
3798
3843
  kind: "boot",
3799
- modules: bootBounded ? useClosure(route, reach, bootSeeds, {}, bootSeeds) : useClosure(route, reach, bootRoots)
3844
+ modules: bootBounded ? useClosure(route, reach, bootSeeds, bootBound, bootSeeds) : useClosure(route, reach, bootRoots)
3800
3845
  }, ...renderRoots.length ? [{
3801
3846
  key: "render",
3802
3847
  kind: "render",
@@ -3806,12 +3851,14 @@ function computeInteractionClosures(input) {
3806
3851
  const merged = demand.get(file);
3807
3852
  const fileSymbols = symbolsByFile.get(file) ?? [];
3808
3853
  for (const [actionKey, action] of [...merged.actions].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
3809
- const firstUse = merged.replaced ? null : action.firstUse;
3854
+ const lean = isLeanAction(action.runtimeModuleIds);
3855
+ const served = lean && action.lean || action;
3856
+ const firstUse = merged.replaced ? null : served.firstUse;
3810
3857
  const joined = firstUse ? joinPage([...firstUse.map((reach) => ({
3811
3858
  file,
3812
3859
  reach
3813
3860
  })), ...page.resume], page) : null;
3814
- if (action.unknown || joined === "unknown") {
3861
+ if (served.unknown || joined === "unknown") {
3815
3862
  consumers.push({
3816
3863
  key: `action:${display(file, input.root)}#${actionKey}`,
3817
3864
  kind: "action",
@@ -3847,7 +3894,7 @@ function computeInteractionClosures(input) {
3847
3894
  else widen("unresolved-symbol");
3848
3895
  }
3849
3896
  }
3850
- const runtimeIds = /* @__PURE__ */ new Set([...action.runtimeModuleIds, ...joined?.runtimeModuleIds ?? []]);
3897
+ const runtimeIds = /* @__PURE__ */ new Set([...lean && joined ? [] : action.runtimeModuleIds, ...joined?.runtimeModuleIds ?? []]);
3851
3898
  if (merged.replaced || !firstUse && [...action.recordKinds].some((kind) => CARRIES_UNLISTED_RECORDS[kind])) {
3852
3899
  widen("unlisted-records");
3853
3900
  for (const id of merged.unknownRecordModuleIds) runtimeIds.add(id);
@@ -3857,7 +3904,7 @@ function computeInteractionClosures(input) {
3857
3904
  key: `action:${display(file, input.root)}#${actionKey}`,
3858
3905
  kind: "action",
3859
3906
  ...conservative ? { conservative } : {},
3860
- ...[...action.runtimeModuleIds].some((id) => LEAN_DISPATCH_MODULE_IDS.has(id)) ? { lean: true } : {},
3907
+ ...lean ? { lean: true } : {},
3861
3908
  modules: useClosure(route, reach, seeds, { runtimeIds }, seeds)
3862
3909
  });
3863
3910
  }
@@ -3937,6 +3984,7 @@ function mergeDemand(sources, landingArmsServed) {
3937
3984
  replaced: false,
3938
3985
  records: /* @__PURE__ */ new Map(),
3939
3986
  landingSymbols: /* @__PURE__ */ new Set(),
3987
+ landingRuntimeModuleIds: /* @__PURE__ */ new Set(),
3940
3988
  actions: /* @__PURE__ */ new Map(),
3941
3989
  unknownRecordModuleIds: /* @__PURE__ */ new Set(),
3942
3990
  page: {
@@ -3959,7 +4007,9 @@ function mergeDemand(sources, landingArmsServed) {
3959
4007
  entry.records.set(record.recordId, symbols);
3960
4008
  if (landingArmsServed && record.kind === "async-boundary") continue;
3961
4009
  for (const id of record.symbolIds ?? []) symbols.add(id);
3962
- if (RUNS_WITHOUT_INPUT[record.kind]) for (const id of record.symbolIds ?? []) entry.landingSymbols.add(id);
4010
+ if (!RUNS_WITHOUT_INPUT[record.kind]) continue;
4011
+ for (const id of record.symbolIds ?? []) entry.landingSymbols.add(id);
4012
+ for (const id of record.runtimeModuleIds) entry.landingRuntimeModuleIds.add(id);
3963
4013
  }
3964
4014
  for (const action of [...map.actions, ...map.armActions ?? []]) {
3965
4015
  const key = `${action.hostNodeId}:${action.eventName}`;
@@ -3972,9 +4022,14 @@ function mergeDemand(sources, landingArmsServed) {
3972
4022
  firstUse: action.firstUse ? [] : null,
3973
4023
  unknown: false
3974
4024
  };
3975
- if (action.firstUse === "unknown") existing.unknown = true;
3976
- else if (!action.firstUse) existing.firstUse = null;
3977
- else existing.firstUse?.push(action.firstUse);
4025
+ const views = [existing];
4026
+ if (isLeanAction(action.runtimeModuleIds)) views.push(existing.lean ??= {
4027
+ firstUse: action.firstUse ? [] : null,
4028
+ unknown: false
4029
+ });
4030
+ for (const view of views) if (action.firstUse === "unknown") view.unknown = true;
4031
+ else if (!action.firstUse) view.firstUse = null;
4032
+ else view.firstUse?.push(action.firstUse);
3978
4033
  for (const kind of action.recordKinds) existing.recordKinds.add(kind);
3979
4034
  for (const id of action.payloadRecordIds) existing.recordIds.add(id);
3980
4035
  for (const id of action.runtimeModuleIds) existing.runtimeModuleIds.add(id);
@@ -4699,7 +4754,8 @@ function throwLinkedModuleChildDiagnostics(metadata, children, parentManifest) {
4699
4754
  captureMetadataForSource: (source) => metadata.captureMetadataForSource(source),
4700
4755
  parentCaptureMetadataForSource: (parent) => parentManifest?.captureMetadata ?? metadata.captureMetadataForSource(pathname$1(parent))
4701
4756
  });
4702
- if (diagnostic) throw new Error(diagnostic.message);
4757
+ if (!diagnostic) return;
4758
+ throw (diagnostic.source === void 0 ? void 0 : metadata.compileFailure(diagnostic.source)) ?? new Error(diagnostic.message);
4703
4759
  }
4704
4760
  //#endregion
4705
4761
  //#region src/build/linked-interfaces.ts
@@ -4949,6 +5005,13 @@ var ModuleMetadataRegistry = class ModuleMetadataRegistry {
4949
5005
  publication.pending.delete(emittedModule);
4950
5006
  ModuleMetadataRegistry.#changed(publication);
4951
5007
  }
5008
+ /** The error the source's latest compile threw, in any environment, if nothing has published since. */
5009
+ compileFailure(source) {
5010
+ for (const [key, publication] of this.#sourceClaimPublications) {
5011
+ if (key.slice(key.indexOf("\0") + 1) !== source) continue;
5012
+ for (const failure of publication.failed.values()) return failure;
5013
+ }
5014
+ }
4952
5015
  /**
4953
5016
  * Drops an edited module's claims and the ledger entry that remembers it ever
4954
5017
  * published them, so the transform that recompiles it counts as a first
@@ -5058,6 +5121,7 @@ var ModuleMetadataRegistry = class ModuleMetadataRegistry {
5058
5121
  const publication = this.#sourceClaimPublications.get(publicationKey(environment, source));
5059
5122
  if (!publication || ModuleMetadataRegistry.#complete(publication)) return;
5060
5123
  const unpublished = [...publication.begun].filter((emittedModule) => !publication.published.has(emittedModule));
5124
+ ModuleMetadataRegistry.#throwFailure(publication, unpublished);
5061
5125
  throw new Error(`MARKLESS_SOURCE_SYMBOL_CLAIMS_UNSEALED: Source ${JSON.stringify(source)} claims were consumed before final publication completed. Emitted variants that have not published: ${unpublished.map((emittedModule) => JSON.stringify(emittedModule)).join(", ")}.`);
5062
5126
  }
5063
5127
  emittedSymbolClaimMap(emittedModules) {
@@ -6731,7 +6795,30 @@ function stripImportedVitePreloadHelper(code) {
6731
6795
  const withoutImport = code.slice(0, helper.importStart) + helper.keptImport + code.slice(helper.importEnd);
6732
6796
  if (preloadStillCalled(code, withoutImport, helper)) return code;
6733
6797
  const initCall = `${escapeRegExp$1(helper.initFunction)}\\(\\)`;
6734
- return withoutImport.replace(new RegExp(String.raw`,${initCall},`, "g"), ",").replace(new RegExp(String.raw`\{${initCall},`, "g"), "{").replace(new RegExp(String.raw`,${initCall},`, "g"), ",").replace(new RegExp(String.raw`,${initCall}\}`, "g"), "}").replace(new RegExp(String.raw`\{${initCall}\}`, "g"), "{}");
6798
+ return withoutInitStatements(withoutImport.replace(new RegExp(String.raw`,${initCall},`, "g"), ",").replace(new RegExp(String.raw`\{${initCall},`, "g"), "{").replace(new RegExp(String.raw`,${initCall},`, "g"), ",").replace(new RegExp(String.raw`,${initCall}\}`, "g"), "}").replace(new RegExp(String.raw`\{${initCall}\}`, "g"), "{}"), helper.initFunction) ?? code;
6799
+ }
6800
+ function withoutInitStatements(code, name) {
6801
+ const offsets = calleeOffsets(code, name);
6802
+ if (offsets.length === 0) return code;
6803
+ const program = tryParseJavaScriptModule(code);
6804
+ if (!program) return void 0;
6805
+ const statements = [];
6806
+ walkReferenceScopes(program, [], {
6807
+ removedImports: /* @__PURE__ */ new Set(),
6808
+ offsets
6809
+ }, (node, scopes) => {
6810
+ const call = node.type === "ExpressionStatement" ? node.expression : void 0;
6811
+ if (call?.type !== "CallExpression" || identifierName$1(call.callee) !== name || asNodes$1(call.arguments).length > 0 || isDeclaredInScope(name, scopes)) return;
6812
+ statements.push(node);
6813
+ });
6814
+ let next = code;
6815
+ for (const { start, end } of statements.sort((left, right) => right.start - left.start)) {
6816
+ const before = next.slice(0, start).trimEnd();
6817
+ const own = before === "" || /[;{]$/.test(before);
6818
+ next = next.slice(0, start) + (own ? "" : ";") + next.slice(end);
6819
+ }
6820
+ const after = tryParseJavaScriptModule(next);
6821
+ return after && !callsFreeName(next, after, name, /* @__PURE__ */ new Set()) ? next : void 0;
6735
6822
  }
6736
6823
  function findImportedVitePreloadHelper(code) {
6737
6824
  if (!code.includes("__vitePreload") || !code.includes("init_preload_helper")) return void 0;
@@ -8183,7 +8270,8 @@ async function loadHook(ctx, pluginContext, id) {
8183
8270
  const normalizedId = normalizeVirtualId$2(id);
8184
8271
  const resolverSource = resolverVirtualModuleSourceFile(normalizedId);
8185
8272
  const symbolSource = symbolVirtualModuleSourceFile(normalizedId);
8186
- const ownerSource = resolverSource ?? symbolSource;
8273
+ const renderDataSource = normalizedId.startsWith(`virtual:markless:render-data:`) ? marklessVirtualModuleSourceFile(normalizedId, ctx.getRoot()) : null;
8274
+ const ownerSource = resolverSource ?? symbolSource ?? renderDataSource;
8187
8275
  if (ownerSource) await moduleMetadata.awaitSourceClaimsPublished(ctx.getEnvironment(pluginContext), ownerSource);
8188
8276
  if (resolverSource && ctx.getEnvironment(pluginContext) === "client" && internalOptions.dev !== true && internalOptions.prerenderWakeChannel === true && typeof pluginContext.getModuleInfo === "function") {
8189
8277
  const queryClaimSources = [
@@ -8537,6 +8625,7 @@ function planTransformHookRequest(ctx, pluginContext, code, id, currentEnvironme
8537
8625
  moduleId: moduleIdFor(source, ctx.getRoot()),
8538
8626
  source: code,
8539
8627
  serverOnlyProps: internalOptions.serverOnlyProps?.(moduleIdFor(source, ctx.getRoot())),
8628
+ routeRoot: internalOptions.unimportedRouteModule?.(moduleIdFor(source, ctx.getRoot())) === true,
8540
8629
  dev: plan.dev,
8541
8630
  buildId: internalOptions.buildId,
8542
8631
  executionLog: normalizeExecutionLogMode(internalOptions.executionLog),
@@ -8977,6 +9066,52 @@ async function importedConstantsUnchanged(pluginContext, importer, input) {
8977
9066
  return JSON.stringify(current) === JSON.stringify(known);
8978
9067
  }
8979
9068
  //#endregion
9069
+ //#region src/composed-route-modules.ts
9070
+ const SCANNED = /* @__PURE__ */ new Set([
9071
+ ".ts",
9072
+ ".tsx",
9073
+ ".mts",
9074
+ ".js",
9075
+ ".jsx",
9076
+ ".mjs",
9077
+ ".tsrx",
9078
+ ".mdx"
9079
+ ]);
9080
+ const SKIPPED_DIRS = /* @__PURE__ */ new Set([
9081
+ "node_modules",
9082
+ "dist",
9083
+ ".output",
9084
+ ".nitro",
9085
+ ".git"
9086
+ ]);
9087
+ const SPECIFIER = /(?:\bfrom|\bimport|\bimport\s*\()\s*['"]([^'"]*\.(?:tsrx|mdx)(?:\?[^'"]*)?)['"]/g;
9088
+ /**
9089
+ * The page modules some file in the app imports. A page nothing imports is
9090
+ * rendered only by the router, so its props never change in the browser; one
9091
+ * that is imported may be rendered as a child whose props can.
9092
+ */
9093
+ async function importedRouteModules(input) {
9094
+ const imported = /* @__PURE__ */ new Set();
9095
+ const visit = async (dir) => {
9096
+ const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
9097
+ await Promise.all(entries.map(async (entry) => {
9098
+ const path = join(dir, entry.name);
9099
+ if (entry.isDirectory()) {
9100
+ if (!SKIPPED_DIRS.has(entry.name) && !entry.name.startsWith(".")) await visit(path);
9101
+ return;
9102
+ }
9103
+ if (!SCANNED.has(extname(entry.name))) return;
9104
+ const source = await readFile(path, "utf8").catch(() => "");
9105
+ for (const [, specifier] of source.matchAll(SPECIFIER)) {
9106
+ const file = (await input.resolve(specifier, path))?.split("?")[0];
9107
+ if (file && file !== path && input.isRoute(file)) imported.add(file);
9108
+ }
9109
+ }));
9110
+ };
9111
+ await visit(input.root);
9112
+ return imported;
9113
+ }
9114
+ //#endregion
8980
9115
  //#region src/rolldown.ts
8981
9116
  const marklessClient = (options = {}) => createMarklessRolldownPlugin({
8982
9117
  environment: "client",
@@ -9050,6 +9185,9 @@ function createMarklessRolldownPlugin(input) {
9050
9185
  },
9051
9186
  declareServerOnlyProps: (resolve) => {
9052
9187
  internalOptions.serverOnlyProps = resolve;
9188
+ },
9189
+ declareRouteModules: (isRoute) => {
9190
+ internalOptions.routeModules = isRoute;
9053
9191
  }
9054
9192
  },
9055
9193
  name,
@@ -9067,6 +9205,16 @@ function createMarklessRolldownPlugin(input) {
9067
9205
  dev.reset();
9068
9206
  clearParsedChunkCode();
9069
9207
  const currentRoot = getRoot();
9208
+ const isRoute = internalOptions.routeModules;
9209
+ if (isRoute && internalOptions.dev !== true && currentRoot) {
9210
+ const imported = await importedRouteModules({
9211
+ root: currentRoot,
9212
+ isRoute: (file) => isRoute(moduleIdFor(file, currentRoot)),
9213
+ resolve: async (specifier, importer) => (await this.resolve(specifier, importer, { skipSelf: true }).catch(() => null))?.id
9214
+ });
9215
+ const importedIds = new Set([...imported].map((file) => moduleIdFor(file, currentRoot)));
9216
+ internalOptions.unimportedRouteModule = (moduleId) => isRoute(moduleId) && !importedIds.has(moduleId);
9217
+ } else internalOptions.unimportedRouteModule = void 0;
9070
9218
  if (getEnvironment(this) === "client") for (const source of clientSymbolEntries(input.input, currentRoot)) clientSymbolEntrySources.add(source);
9071
9219
  },
9072
9220
  buildEnd: packing?.buildEnd,
@@ -9104,7 +9252,10 @@ function createMarklessRolldownPlugin(input) {
9104
9252
  if (stale.length > 0) this.error(staleChunkNamesMessage(stale));
9105
9253
  const unmapped = unmappedChunkSpecifiers(bundle);
9106
9254
  if (unmapped.length > 0) this.error(`Markless emitted chunks that import specifiers its import map does not resolve to an emitted chunk: ${unmapped.join(", ")}. A plugin changed chunk code or file names after the Markless finalize pass. ${DEBUGGING_PLAYBOOK_HINT}`);
9107
- if (output.dir) await moveImportMapOutOfClientOutput(output.dir, MARKLESS_IMPORT_MAP_ASSET in bundle);
9255
+ if (output.dir) {
9256
+ await moveImportMapOutOfClientOutput(output.dir, MARKLESS_IMPORT_MAP_ASSET in bundle);
9257
+ await moveBuildMetadataOutOfClientOutput(output.dir, new Set(Object.keys(bundle)), { executionLogActive: executionLogActivationInjection(internalOptions.executionLog) !== null });
9258
+ }
9108
9259
  }
9109
9260
  };
9110
9261
  }
@@ -9113,4 +9264,4 @@ function pluginName(environment) {
9113
9264
  return `markless:rolldown:${environment}`;
9114
9265
  }
9115
9266
  //#endregion
9116
- export { inlineDeferSource as A, importMapScript as C, transformTsrxModule as D, preflightTsrxModuleDiagnostics as E, INLINE_DEFER_LOADER_SOURCE as O, MARKLESS_IMPORT_MAP_ASSET as S, prefetchChunkParses as T, createPreloadGraphAdder as _, collapseInitFacadeImports as a, marklessImportMapPath as b, collectHeadLinkInjections as c, nativePackingEnabled as d, nativePackingPlugins as f, convertManifestToBundleGraph as g, withUndemandedReExportDoors as h, marklessServer as i, createInlineDeferTriggerSource as k, marklessRuntimeSpecifierId as l, undemandedRuntimeModules as m, marklessClient as n, unwrapAsyncImportWrappers as o, isReExportDoor as p, marklessLib as r, createBuildMetadata as s, createMarklessRolldownPlugin as t, DEPRECATED_NATIVE_PACKING_WARNING as u, runtimeModuleIdFromOrigin as v, insertImportMapScript as w, MARKLESS_CHUNK_SPECIFIER_PREFIX as x, marklessBuildManifestDir as y };
9267
+ export { createInlineDeferTriggerSource as A, MARKLESS_IMPORT_MAP_ASSET as C, preflightTsrxModuleDiagnostics as D, prefetchChunkParses as E, transformTsrxModule as O, MARKLESS_CHUNK_SPECIFIER_PREFIX as S, insertImportMapScript as T, createPreloadGraphAdder as _, collapseInitFacadeImports as a, marklessBuildManifestPath as b, collectHeadLinkInjections as c, nativePackingEnabled as d, nativePackingPlugins as f, convertManifestToBundleGraph as g, withUndemandedReExportDoors as h, marklessServer as i, inlineDeferSource as j, INLINE_DEFER_LOADER_SOURCE as k, marklessRuntimeSpecifierId as l, undemandedRuntimeModules as m, marklessClient as n, unwrapAsyncImportWrappers as o, isReExportDoor as p, marklessLib as r, createBuildMetadata as s, createMarklessRolldownPlugin as t, DEPRECATED_NATIVE_PACKING_WARNING as u, runtimeModuleIdFromOrigin as v, importMapScript as w, marklessImportMapPath as x, marklessBuildManifestDir as y };
@@ -1,5 +1,5 @@
1
- import { _ as TransformTsrxModuleInput, a as MarklessBundle, c as MarklessEnvironment, d as MarklessRolldownPluginApi, f as MarklessTransformManifest, g as PreloadGraphEntriesAdder, h as PreloadGraphEntries, i as MarklessBuildMetadata, l as MarklessManifest, m as PreloadGraphContext, n as GlobalInjections, o as MarklessBundleGraph, p as MarklessVirtualModule, r as MarklessAsset, s as MarklessDevServer, t as BundleGraphAdder, u as MarklessRolldownOptions, v as TransformTsrxModuleResult } from "./types-BqSoEVp6.js";
2
- import { a as resumeVirtualModuleId, n as MARKLESS_VIRTUAL_PREFIX, r as prerenderWakeVirtualModuleId } from "./execution-log-D9cex1i1.js";
1
+ import { _ as TransformTsrxModuleInput, a as MarklessBundle, c as MarklessEnvironment, d as MarklessRolldownPluginApi, f as MarklessTransformManifest, g as PreloadGraphEntriesAdder, h as PreloadGraphEntries, i as MarklessBuildMetadata, l as MarklessManifest, m as PreloadGraphContext, n as GlobalInjections, o as MarklessBundleGraph, p as MarklessVirtualModule, r as MarklessAsset, s as MarklessDevServer, t as BundleGraphAdder, u as MarklessRolldownOptions, v as TransformTsrxModuleResult } from "./types-iOUoceJ-.js";
2
+ import { a as resumeVirtualModuleId, n as MARKLESS_VIRTUAL_PREFIX, r as prerenderWakeVirtualModuleId } from "./execution-log-BL-7a77M.js";
3
3
  import { ProtocolStatePayload, ProtocolViewPayload } from "@markless/serializer";
4
4
  import { ArtifactChildMaterialization, CompilerDiagnostic, ModuleGraphInterfaceArtifact, SemanticGraphInput } from "@markless/compiler";
5
5
  import "@markless/web/inline/resumer";
@@ -18,6 +18,7 @@ type Environment = MarklessEnvironment | ((context: unknown) => MarklessEnvironm
18
18
  export declare const MARKLESS_BUILD_PREFIX = "build/";
19
19
  export declare const MARKLESS_BUNDLE_GRAPH = "build/bundle-graph.json";
20
20
  export declare const MARKLESS_BUILD_METADATA_FILES: readonly ["build/bundle-graph.json", "build/execution-sizes.json", "build/execution-demand.json", "build/interaction-closures.json", "build/byte-attribution.json"];
21
+ export declare const MARKLESS_PUBLIC_BUILD_METADATA_FILES: readonly ["build/execution-sizes.json"];
21
22
  export declare function outputDefaults(output: OutputOptions, environment: MarklessEnvironment): OutputOptions;
22
23
  //#endregion
23
24
  //#region src/build/build-metadata.d.ts
@@ -76,6 +77,8 @@ export declare function collectHeadLinkInjections(bundle: HeadLinkBundle, option
76
77
  //#region src/build/build-manifests.d.ts
77
78
  /** Where build-time hand-off files for a client output live: beside it, never inside the directory a host serves. */
78
79
  export declare function marklessBuildManifestDir(clientOutDir: string): string;
80
+ /** Where a build metadata file such as `build/bundle-graph.json` lands for a client output. */
81
+ export declare function marklessBuildManifestPath(clientOutDir: string, metadataFile: string): string;
79
82
  /** The chunk import map a packed client build hands to the server that renders its documents. */
80
83
  export declare function marklessImportMapPath(clientOutDir: string): string;
81
84
  //#endregion
package/dist/rolldown.js CHANGED
@@ -1,3 +1,3 @@
1
- import { X as MARKLESS_BUILD_PREFIX, Y as MARKLESS_BUILD_METADATA_FILES, Z as MARKLESS_BUNDLE_GRAPH, ht as resumeVirtualModuleId, nt as outputDefaults, pt as prerenderWakeVirtualModuleId, rt as MARKLESS_VIRTUAL_PREFIX } from "./route-pack-groups-BpefyjrE.js";
2
- import { C as importMapScript, D as transformTsrxModule, S as MARKLESS_IMPORT_MAP_ASSET, _ as createPreloadGraphAdder, b as marklessImportMapPath, c as collectHeadLinkInjections, g as convertManifestToBundleGraph, i as marklessServer, n as marklessClient, r as marklessLib, s as createBuildMetadata, t as createMarklessRolldownPlugin, w as insertImportMapScript, x as MARKLESS_CHUNK_SPECIFIER_PREFIX, y as marklessBuildManifestDir } from "./rolldown-BciZw5hZ.js";
3
- export { MARKLESS_BUILD_METADATA_FILES, MARKLESS_BUILD_PREFIX, MARKLESS_BUNDLE_GRAPH, MARKLESS_CHUNK_SPECIFIER_PREFIX, MARKLESS_IMPORT_MAP_ASSET, MARKLESS_VIRTUAL_PREFIX, collectHeadLinkInjections, convertManifestToBundleGraph, createBuildMetadata, createMarklessRolldownPlugin, createPreloadGraphAdder, importMapScript, insertImportMapScript, marklessBuildManifestDir, marklessClient, marklessImportMapPath, marklessLib, marklessServer, outputDefaults, prerenderWakeVirtualModuleId, resumeVirtualModuleId, transformTsrxModule };
1
+ import { $ as MARKLESS_BUNDLE_GRAPH, Q as MARKLESS_BUILD_PREFIX, Z as MARKLESS_BUILD_METADATA_FILES, at as outputDefaults, gt as prerenderWakeVirtualModuleId, it as MARKLESS_PUBLIC_BUILD_METADATA_FILES, ot as MARKLESS_VIRTUAL_PREFIX, vt as resumeVirtualModuleId } from "./route-pack-groups-BXc755qH.js";
2
+ import { C as MARKLESS_IMPORT_MAP_ASSET, O as transformTsrxModule, S as MARKLESS_CHUNK_SPECIFIER_PREFIX, T as insertImportMapScript, _ as createPreloadGraphAdder, b as marklessBuildManifestPath, c as collectHeadLinkInjections, g as convertManifestToBundleGraph, i as marklessServer, n as marklessClient, r as marklessLib, s as createBuildMetadata, t as createMarklessRolldownPlugin, w as importMapScript, x as marklessImportMapPath, y as marklessBuildManifestDir } from "./rolldown-DHkCX7vL.js";
3
+ export { MARKLESS_BUILD_METADATA_FILES, MARKLESS_BUILD_PREFIX, MARKLESS_BUNDLE_GRAPH, MARKLESS_CHUNK_SPECIFIER_PREFIX, MARKLESS_IMPORT_MAP_ASSET, MARKLESS_PUBLIC_BUILD_METADATA_FILES, MARKLESS_VIRTUAL_PREFIX, collectHeadLinkInjections, convertManifestToBundleGraph, createBuildMetadata, createMarklessRolldownPlugin, createPreloadGraphAdder, importMapScript, insertImportMapScript, marklessBuildManifestDir, marklessBuildManifestPath, marklessClient, marklessImportMapPath, marklessLib, marklessServer, outputDefaults, prerenderWakeVirtualModuleId, resumeVirtualModuleId, transformTsrxModule };
@@ -447,17 +447,52 @@ function scalarPlanSourceReference(source) {
447
447
  }
448
448
  //#endregion
449
449
  //#region src/rebound-symbol-route.ts
450
- function emitReboundSymbolRoute(route, reboundName, localLoader, unboundLoad, indent) {
451
- if (!hasBoundSymbols(route)) return [];
452
- const rest = `symbolId.slice(${route.prefix.length})`;
453
- return [`${indent}const bound = ${JSON.stringify(route.boundSymbols)};`, `${indent}if (Object.hasOwn(bound, ${rest})) return ${reboundName}(${localLoader}(bound[${rest}]), ${JSON.stringify(route.prefix)}, () => ${unboundLoad});`];
454
- }
455
450
  function emitReboundSymbolImport(routes, reboundName) {
456
451
  return routes.some(hasBoundSymbols) ? `import { marklessReboundSymbol as ${reboundName} } from '@markless/web/fns/rebound-symbol';` : "";
457
452
  }
458
453
  function hasBoundSymbols(route) {
459
454
  return route.boundSymbols !== void 0 && Object.keys(route.boundSymbols).length > 0;
460
455
  }
456
+ /**
457
+ * One loader for every composed child route, driven by a table: a page with many
458
+ * instances of a child adds a row per instance, not a copy of the loader.
459
+ */
460
+ function emitSymbolRouteTable(input) {
461
+ const { routes, functionName, fallbackName, reboundName } = input;
462
+ const sources = [...new Set(routes.flatMap((route) => route.importSource ? [route.importSource] : []))];
463
+ const keyLists = [];
464
+ const table = routes.map((route) => `[${JSON.stringify(route.prefix)}, ${route.importSource ? sources.indexOf(route.importSource) : -1}, ${hasBoundSymbols(route) ? boundEntry(route.boundSymbols, keyLists) : 0}]`);
465
+ return [
466
+ emitReboundSymbolImport(routes, reboundName),
467
+ `const ${functionName}Imports = [${sources.map((source) => `() => import(${JSON.stringify(source)})`).join(", ")}];`,
468
+ keyLists.length > 0 ? `const ${functionName}BoundKeys = [${keyLists.join(", ")}];` : "",
469
+ `const ${functionName}Routes = [${table.join(", ")}];`,
470
+ `${input.exported ? "export " : ""}function ${functionName}(symbolId) {`,
471
+ `\tfor (const [prefix, at, bound] of ${functionName}Routes) {`,
472
+ " if (!symbolId.startsWith(prefix)) continue;",
473
+ " const rest = symbolId.slice(prefix.length);",
474
+ `\t\tconst unbound = () => at < 0 ? (prefix ? ${functionName}(rest) : ${fallbackName}(rest)) : ${functionName}Imports[at]().then((mod) => mod.loadSymbol ? mod.loadSymbol(rest) : Promise.reject(new Error(\`Unknown child async symbol \${symbolId}\`)));`,
475
+ hasAnyBound(routes) ? [keyLists.length > 0 ? `\t\tconst boundId = !bound ? undefined : Array.isArray(bound) ? (${functionName}BoundKeys[bound[1]].includes(rest) ? \`bound:\${encodeURIComponent(rest)}:\${bound[0]}\` : undefined) : Object.hasOwn(bound, rest) ? bound[rest] : undefined;` : " const boundId = bound && Object.hasOwn(bound, rest) ? bound[rest] : undefined;", `\t\tif (boundId) return ${reboundName}(${fallbackName}(boundId), prefix, unbound);`].join("\n") : "",
476
+ " return unbound();",
477
+ " }",
478
+ `\treturn ${fallbackName}(symbolId);`,
479
+ "}"
480
+ ].filter((line) => line !== "").join("\n");
481
+ }
482
+ function boundEntry(boundSymbols, keyLists) {
483
+ const entries = Object.entries(boundSymbols);
484
+ const [firstKey, firstId] = entries[0];
485
+ const head = `bound:${encodeURIComponent(firstKey)}:`;
486
+ const suffix = firstId.startsWith(head) ? firstId.slice(head.length) : void 0;
487
+ if (suffix === void 0 || entries.some(([key, id]) => id !== `bound:${encodeURIComponent(key)}:${suffix}`)) return JSON.stringify(boundSymbols);
488
+ const keys = JSON.stringify(entries.map(([key]) => key));
489
+ let index = keyLists.indexOf(keys);
490
+ if (index < 0) index = keyLists.push(keys) - 1;
491
+ return `[${JSON.stringify(suffix)}, ${index}]`;
492
+ }
493
+ function hasAnyBound(routes) {
494
+ return routes.some(hasBoundSymbols);
495
+ }
461
496
  //#endregion
462
497
  //#region src/source-module.ts
463
498
  const MARKLESS_VIRTUAL_PREFIX = "virtual:markless:";
@@ -725,8 +760,8 @@ function emitRowMintLoaderInstall() {
725
760
  * The same one line for per-enclosing-row wiring: only a page holding a `@for`
726
761
  * inside another `@for`'s rows names the module, so no other app emits its chunk.
727
762
  */
728
- function nestedRepeatsLoader(runtimeDemandMap) {
729
- return demandsKeyedRepeatModule(runtimeDemandMap, NESTED_REPEATS_RUNTIME_MODULE_ID) ? ["globalThis.__marklessNestedRepeats ??= (...input) =>", " import('@markless/web/fns/nested-repeats').then((nested) => nested.wireNestedRepeats(...input));"].join("\n") : null;
763
+ function nestedRepeatsLoader(runtimeDemandMap, linked = false) {
764
+ return linked || demandsKeyedRepeatModule(runtimeDemandMap, NESTED_REPEATS_RUNTIME_MODULE_ID) ? ["globalThis.__marklessNestedRepeats ??= (...input) =>", " import('@markless/web/fns/nested-repeats').then((nested) => nested.wireNestedRepeats(...input));"].join("\n") : null;
730
765
  }
731
766
  /**
732
767
  * True when the compiler folded the mint into a keyed-repeat record - which it
@@ -762,8 +797,8 @@ function componentRowLoader(input) {
762
797
  return input.linkedRowSlotReaders || demandsKeyedRepeatModule(input.runtimeDemandMap, ROW_SLOT_MINT_RUNTIME_MODULE_ID) ? emitRowSlotMintLoaderInstall() : void 0;
763
798
  }
764
799
  function clientRowMintLoader(input) {
765
- const mint = demandsRowComponentMint(input.runtimeDemandMap) ? emitRowComponentMintLoaderInstall() : componentRowLoader(input) ?? (demandsRowMint(input.runtimeDemandMap) ? emitRowMintLoaderInstall() : null);
766
- const nested = nestedRepeatsLoader(input.runtimeDemandMap);
800
+ const mint = demandsRowComponentMint(input.runtimeDemandMap) ? emitRowComponentMintLoaderInstall() : componentRowLoader(input) ?? (input.linkedRowTemplates || demandsRowMint(input.runtimeDemandMap) ? emitRowMintLoaderInstall() : null);
801
+ const nested = nestedRepeatsLoader(input.runtimeDemandMap, input.linkedNestedRepeats);
767
802
  return mint && nested ? `${mint}\n${nested}` : mint ?? nested;
768
803
  }
769
804
  function emitRowSlotMintLoaderInstall() {
@@ -798,7 +833,7 @@ function emitResumeModule(input) {
798
833
  runtimeDemandMap: input.servedScalarPlans
799
834
  } : input);
800
835
  const stagedPrerender = (input.prerenderTriggerGroups?.length ?? 0) > 0;
801
- const resumeContainerEvent = emitQueuedResumeContainerEvent(emitResumeContainerEvent(resumeSymbolLoader, input.needsFullResume ?? false, input.payloadState?.version === ASYNC_PROTOCOL_VERSION, servedPlansOnly ? "scalar" : composedLeanMode(input.symbolRoutes.length > 0, leanResumeMode(input.runtimeDemandMap)), scalarSpecializations, input.runtimeDemandMap, input.executionLog !== "never", input.prerenderDataId, stagedPrerender, componentRowLoader(input) ? input.lazyRenderDataId ?? input.renderDataId : void 0, input.symbolRoutes.length > 0 || servedPlansOnly, (input.closurePlanRoutes ?? []).some((route) => "importSource" in route) && scalarSpecializations.length > 0 && !input.prerenderDataId, input.streamsArms === true));
836
+ const resumeContainerEvent = emitQueuedResumeContainerEvent(emitResumeContainerEvent(resumeSymbolLoader, input.needsFullResume ?? false, input.storageCells !== true && input.payloadState?.version === ASYNC_PROTOCOL_VERSION, servedPlansOnly ? "scalar" : composedLeanMode(input.symbolRoutes.length > 0, leanResumeMode(input.runtimeDemandMap)), scalarSpecializations, input.runtimeDemandMap, input.executionLog !== "never", input.prerenderDataId, stagedPrerender, componentRowLoader(input) ? input.lazyRenderDataId ?? input.renderDataId : void 0, input.symbolRoutes.length > 0 || servedPlansOnly, (input.closurePlanRoutes ?? []).some((route) => "importSource" in route) && scalarSpecializations.length > 0 && !input.prerenderDataId, input.streamsArms === true));
802
837
  const closureImports = [
803
838
  "marklessClosureRouted",
804
839
  "marklessPrimeClosure",
@@ -818,8 +853,8 @@ function emitResumeModule(input) {
818
853
  ].join("\n") : input.rosterDerivation === true ? emitRosterResumeLoaderInstall() : null,
819
854
  demandsOverlay(input.runtimeDemandMap) ? emitOverlayLoaderInstall() : null,
820
855
  input.hasIdleEvents ? emitIdleTriggerInstall() : null,
821
- componentRowLoader(input) ?? (demandsRowMint(input.runtimeDemandMap) ? emitRowMintLoaderInstall() : null),
822
- nestedRepeatsLoader(input.runtimeDemandMap),
856
+ componentRowLoader(input) ?? (input.linkedRowTemplates || demandsRowMint(input.runtimeDemandMap) ? emitRowMintLoaderInstall() : null),
857
+ nestedRepeatsLoader(input.runtimeDemandMap, input.linkedNestedRepeats),
823
858
  scalarSpecializations.length > 0 ? [
824
859
  "import { marklessDecodeScalarCell, marklessReadScalarCell, marklessScalarSpecializedError } from '@markless/web/fns/scalar-specialized';",
825
860
  resumeContainerEvent.includes("marklessScalarServedOwner") ? `import { marklessScalarLocate, marklessScalarServedOwner, marklessScalarServedPrime${resumeContainerEvent.includes("marklessScalarServedRecord") ? ", marklessScalarServedRecord" : ""} } from '@markless/web/fns/scalar-served';` : "",
@@ -855,7 +890,7 @@ function emitQueuedResumeContainerEvent(source, { censusRepair = true } = {}) {
855
890
  " const root = input.root;",
856
891
  censusRepair ? " if (root.__marklessShifted) return import('@markless/web/fns/served-census-repair').then((census) => (census.marklessRepairCensus(root), resumeContainerEvent(input)));" : "",
857
892
  " if (!root.__marklessDispatch) {",
858
- " let handler = marklessResumeContainerEvent, tail = Promise.resolve(), done = tail, lastEvent = null, lastEventTime = undefined;",
893
+ " let handler = marklessResumeContainerEvent, tail = Promise.resolve(), done = tail, lastEvent = null, lastEventTime = undefined, seen = new WeakMap();",
859
894
  " root.__marklessRegisterDispatch = next => {",
860
895
  " const fallback = handler;",
861
896
  " handler = input => next(input, fallback);",
@@ -863,7 +898,8 @@ function emitQueuedResumeContainerEvent(source, { censusRepair = true } = {}) {
863
898
  " root.__marklessDispatch = next => {",
864
899
  " const event = next.event, eventTime = event?.timeStamp;",
865
900
  " if (event && next.eventRecord && next.element) event.__marklessPressHost ??= next.element;",
866
- " if (event === lastEvent && eventTime === lastEventTime) return done;",
901
+ " if ((event === lastEvent && eventTime === lastEventTime) || (seen.has(event) && seen.get(event) === eventTime)) return done;",
902
+ " if (Object(event) === event) seen.set(event, eventTime);",
867
903
  " lastEvent = event;",
868
904
  " lastEventTime = eventTime;",
869
905
  " let release;",
@@ -884,23 +920,15 @@ function emitComposedArmRecordsInstall() {
884
920
  }
885
921
  function emitLazySymbolRouteFunction(routes, functionName, fallbackName = "loadSymbol", includeScalarActionPlans = false) {
886
922
  if (routes.length === 0) return "";
887
- const ordered = [...routes].sort((left, right) => right.prefix.length - left.prefix.length);
888
- const reboundName = `${functionName}Rebound`;
889
- return [
890
- emitReboundSymbolImport(ordered, reboundName),
891
- `function ${functionName}(symbolId) {`,
892
- ...ordered.flatMap((route) => {
893
- const unbound = "importSource" in route ? `import(${JSON.stringify(symbolRouteImportSource$1(route.importSource, includeScalarActionPlans))}).then((mod) => mod.loadSymbol ? mod.loadSymbol(symbolId.slice(${route.prefix.length})) : Promise.reject(new Error(\`Unknown child async symbol \${symbolId}\`)))` : `${route.prefix.length > 0 ? functionName : fallbackName}(symbolId.slice(${route.prefix.length}))`;
894
- return [
895
- ` if (symbolId.startsWith(${JSON.stringify(route.prefix)})) {`,
896
- ...emitReboundSymbolRoute(route, reboundName, fallbackName, unbound, " "),
897
- ` return ${unbound};`,
898
- " }"
899
- ];
900
- }),
901
- ` return ${fallbackName}(symbolId);`,
902
- "}"
903
- ].filter((line) => line !== "").join("\n");
923
+ return emitSymbolRouteTable({
924
+ routes: [...routes].sort((left, right) => right.prefix.length - left.prefix.length).map((route) => "importSource" in route ? {
925
+ ...route,
926
+ importSource: symbolRouteImportSource$1(route.importSource, includeScalarActionPlans)
927
+ } : route),
928
+ functionName,
929
+ fallbackName,
930
+ reboundName: `${functionName}Rebound`
931
+ });
904
932
  }
905
933
  function emitsClosurePlanLoader(actions, routes) {
906
934
  return routes.some((route) => "importSource" in route) || actions.some((action) => action.plan?.kind === "closure");
@@ -1296,7 +1324,7 @@ function emitSpecializedScalarDispatcher(actions, loadSymbolName, fallback, reso
1296
1324
  " throw error;",
1297
1325
  " }",
1298
1326
  " }",
1299
- fallback === "fail" ? " return;" : ` return ${fallbackName}(input, "event-match");`,
1327
+ ...fallback === "fail" ? [" return;"] : [" if (input.logOnly) return;", ` return ${fallbackName}(input, "event-match");`],
1300
1328
  "}",
1301
1329
  fallback === "fail" ? "function marklessScalarSpecializedHostMiss(_input, site) { return marklessScalarSpecializedError(\"MARKLESS_SCALAR_SPECIALIZED_HOST_MISS\", site); }" : "function marklessScalarSpecializedHostMiss(input, site) { return marklessScalarSpecializedFallback(input, site); }",
1302
1330
  ...resolution === "static" ? [
@@ -1507,6 +1535,7 @@ const MARKLESS_BUILD_METADATA_FILES = [
1507
1535
  MARKLESS_INTERACTION_CLOSURES,
1508
1536
  MARKLESS_BYTE_ATTRIBUTION
1509
1537
  ];
1538
+ const MARKLESS_PUBLIC_BUILD_METADATA_FILES = [MARKLESS_EXECUTION_SIZES];
1510
1539
  const WEB_RUNTIME_CAPABILITY_GROUPS = [
1511
1540
  {
1512
1541
  name: "markless-direct-renderer",
@@ -1750,21 +1779,16 @@ function emitPrerenderTriggerGroupModule(input) {
1750
1779
  } : route);
1751
1780
  if (routes.length > 0) {
1752
1781
  source = source.replaceAll("loadSymbol(", "marklessLoadLocalSymbol(");
1753
- source += [
1754
- emitReboundSymbolImport(routes, "marklessLoadSymbolRebound"),
1755
- "export function loadSymbol(symbolId) {",
1756
- ...routes.flatMap((route) => {
1757
- const unbound = "importSource" in route ? `import(${JSON.stringify(symbolRouteImportSource(route.importSource))}).then((mod) => mod.loadSymbol ? mod.loadSymbol(symbolId.slice(${route.prefix.length})) : Promise.reject(new Error(\`Unknown child async symbol \${symbolId}\`)))` : `${route.prefix.length > 0 ? "loadSymbol" : "marklessLoadLocalSymbol"}(symbolId.slice(${route.prefix.length}))`;
1758
- return [
1759
- `\tif (symbolId.startsWith(${JSON.stringify(route.prefix)})) {`,
1760
- ...emitReboundSymbolRoute(route, "marklessLoadSymbolRebound", "marklessLoadLocalSymbol", unbound, " "),
1761
- `\t\treturn ${unbound};`,
1762
- " }"
1763
- ];
1764
- }),
1765
- " return marklessLoadLocalSymbol(symbolId);",
1766
- "}"
1767
- ].filter((line) => line !== "").join("\n");
1782
+ source += "\n" + emitSymbolRouteTable({
1783
+ routes: routes.map((route) => "importSource" in route ? {
1784
+ ...route,
1785
+ importSource: symbolRouteImportSource(route.importSource)
1786
+ } : route),
1787
+ functionName: "loadSymbol",
1788
+ fallbackName: "marklessLoadLocalSymbol",
1789
+ reboundName: "marklessLoadSymbolRebound",
1790
+ exported: true
1791
+ });
1768
1792
  }
1769
1793
  return [
1770
1794
  armRendererModuleId ? [
@@ -2363,6 +2387,19 @@ function plannedLandingFiles(bundle) {
2363
2387
  return planned;
2364
2388
  }
2365
2389
  //#endregion
2390
+ //#region src/build/warm-packs.ts
2391
+ function warmPacksSuffix(specifiers) {
2392
+ return `setTimeout(()=>{for(const pack of[${specifiers.map((specifier) => `import(${JSON.stringify(specifier)})`).join(",")}])pack.catch(()=>{})});`;
2393
+ }
2394
+ const WARM_PACKS = /setTimeout\(\(\)=>\{for\((?:const|let|var) ([\w$]+) of\[((?:import\([^)]*\),?)+)\]\)\1\.catch\(\(\)=>\{\}\)\}\)/g;
2395
+ const IMPORT_SPECIFIER = /import\(\s*["'`]([^"'`]+)["'`]\s*\)/g;
2396
+ /** The packs a chunk evaluates a task after it runs, read from `warmPacksSuffix` before or after minifying. */
2397
+ function warmEvaluatedImports(code) {
2398
+ const specifiers = [];
2399
+ for (const warm of code.matchAll(WARM_PACKS)) for (const target of warm[2].matchAll(IMPORT_SPECIFIER)) specifiers.push(target[1]);
2400
+ return specifiers;
2401
+ }
2402
+ //#endregion
2366
2403
  //#region src/build/pack-cost-model.ts
2367
2404
  const PACK_COST_MODEL = {
2368
2405
  roundMs: 162,
@@ -2704,4 +2741,4 @@ function push(map, key, value) {
2704
2741
  else map.set(key, [value]);
2705
2742
  }
2706
2743
  //#endregion
2707
- export { MARKLESS_EXECUTION_DEMAND as $, normalizeVirtualId as A, isExecutionLogChunk as At, sourceForSymbolVirtualImporter as B, isRelativeImport as C, EXECUTION_LOG_DISPATCH_MODULE_IDS as Ct, isScalarPlanSourceRequest as D, executionLogVirtualModuleSource as Dt, isRouteNavigationSourceRequest as E, executionLogActivationInjection as Et, serverSharedSourceRequest as F, emitPrerenderTriggerGroupModule as G, stripBuildPrefix as H, sharedReachedRenderDataRequest as I, adaptImportedCaptureResolver as J, planPrerenderTriggerGroups as K, sourceForPrerenderWakeVirtualImporter as L, renderDataReachedFromQuery as M, requalifyExecutionLogModuleHook as Mt, resolveVirtualId as N, planModulePreloadUrls as Nt, isSymbolOnlySourceRequest as O, hasExecutionLogModuleHook as Ot, resolverVirtualModuleSourceFile as P, planModulePreloads as Pt, MARKLESS_BYTE_ATTRIBUTION as Q, sourceForResumeVirtualImporter as R, isPrerenderWakeSourceRequest as S, withoutFirstUse as St, isResumeSourceRequest as T, MARKLESS_EXECUTION_LOG_MODULE_ID as Tt, virtualModuleSourceForLoad as U, sourceForTriggerGroupVirtualImporter as V, emitPrerenderBoundaryRendererModule as W, MARKLESS_BUILD_PREFIX as X, MARKLESS_BUILD_METADATA_FILES as Y, MARKLESS_BUNDLE_GRAPH as Z, devBrowserVirtualModuleUrl as _, scopedSymbolExportName as _t, isStartupPack as a, STORAGE_FREE_RESUME_ENTRY_SPECIFIER as at, isClientPrimarySourceRequest as b, symbolVirtualModuleId as bt, planRoutePackGroups as c, emitResumeModule as ct, plannedLandingFiles as d, encodedSymbolSource as dt, MARKLESS_EXECUTION_SIZES as et, MARKLESS_ROUTE_SOURCE_QUERY_RE as f, payloadModule as ft, devBrowserSourceModuleUrl as g, rewriteSymbolModuleExport as gt, clientSymbolEntries as h, resumeVirtualModuleId as ht, isMarklessNavigationPack as i, RESUME_ENTRY_SPECIFIER as it, pathname as j, normalizeExecutionLogMode as jt, materializedReachedRenderDataSource as k, injectExecutionLogModuleHook as kt, startupPackOfLazy as l, emitSettleModule as lt, clientRouteArtifactReference as m, prerenderWakeVirtualModuleSourceFile as mt, MARKLESS_NAVIGATION_PACK_PREFIX as n, outputDefaults as nt, lazyStartupPackName as o, demandsOverlay as ot, TSRX_SOURCE_FILE as p, prerenderWakeVirtualModuleId as pt, triggerGroupVirtualModuleId as q, isMarklessDeferredPack as r, MARKLESS_VIRTUAL_PREFIX as rt, marklessDeferredChunkFileNames as s, emitOverlayLoaderInstall as st, MARKLESS_DEFERRED_PACK as t, MARKLESS_INTERACTION_CLOSURES as tt, MARKLESS_INTERACTION_CLOSURES_ASSET as u, emitSourceModule as ut, emittedBundleModuleIds as v, settleVirtualModuleId as vt, isRenderDataSourceRequest as w, MARKLESS_EXECUTION_LOG_GLOBAL as wt, isMarklessRuntimeModule as x, symbolVirtualModuleSourceFile as xt, executionLogRuntimeModuleId as y, symbolEntryVirtualModuleId as yt, sourceForSettleVirtualImporter as z };
2744
+ export { MARKLESS_BUNDLE_GRAPH as $, isSymbolOnlySourceRequest as A, executionLogVirtualModuleSource as At, sourceForResumeVirtualImporter as B, isMarklessRuntimeModule as C, symbolVirtualModuleId as Ct, isResumeSourceRequest as D, MARKLESS_EXECUTION_LOG_GLOBAL as Dt, isRenderDataSourceRequest as E, EXECUTION_LOG_DISPATCH_MODULE_IDS as Et, resolveVirtualId as F, requalifyExecutionLogModuleHook as Ft, virtualModuleSourceForLoad as G, sourceForSymbolVirtualImporter as H, resolverVirtualModuleSourceFile as I, planModulePreloadUrls as It, planPrerenderTriggerGroups as J, emitPrerenderBoundaryRendererModule as K, serverSharedSourceRequest as L, planModulePreloads as Lt, normalizeVirtualId as M, injectExecutionLogModuleHook as Mt, pathname as N, isExecutionLogChunk as Nt, isRouteNavigationSourceRequest as O, MARKLESS_EXECUTION_LOG_MODULE_ID as Ot, renderDataReachedFromQuery as P, normalizeExecutionLogMode as Pt, MARKLESS_BUILD_PREFIX as Q, sharedReachedRenderDataRequest as R, isClientPrimarySourceRequest as S, symbolEntryVirtualModuleId as St, isRelativeImport as T, withoutFirstUse as Tt, sourceForTriggerGroupVirtualImporter as U, sourceForSettleVirtualImporter as V, stripBuildPrefix as W, adaptImportedCaptureResolver as X, triggerGroupVirtualModuleId as Y, MARKLESS_BUILD_METADATA_FILES as Z, clientSymbolEntries as _, prerenderWakeVirtualModuleSourceFile as _t, isStartupPack as a, outputDefaults as at, emittedBundleModuleIds as b, scopedSymbolExportName as bt, planRoutePackGroups as c, STORAGE_FREE_RESUME_ENTRY_SPECIFIER as ct, warmPacksSuffix as d, emitResumeModule as dt, MARKLESS_BYTE_ATTRIBUTION as et, MARKLESS_INTERACTION_CLOSURES_ASSET as f, emitSettleModule as ft, clientRouteArtifactReference as g, prerenderWakeVirtualModuleId as gt, TSRX_SOURCE_FILE as h, payloadModule as ht, isMarklessNavigationPack as i, MARKLESS_PUBLIC_BUILD_METADATA_FILES as it, materializedReachedRenderDataSource as j, hasExecutionLogModuleHook as jt, isScalarPlanSourceRequest as k, executionLogActivationInjection as kt, startupPackOfLazy as l, demandsOverlay as lt, MARKLESS_ROUTE_SOURCE_QUERY_RE as m, encodedSymbolSource as mt, MARKLESS_NAVIGATION_PACK_PREFIX as n, MARKLESS_EXECUTION_SIZES as nt, lazyStartupPackName as o, MARKLESS_VIRTUAL_PREFIX as ot, plannedLandingFiles as p, emitSourceModule as pt, emitPrerenderTriggerGroupModule as q, isMarklessDeferredPack as r, MARKLESS_INTERACTION_CLOSURES as rt, marklessDeferredChunkFileNames as s, RESUME_ENTRY_SPECIFIER as st, MARKLESS_DEFERRED_PACK as t, MARKLESS_EXECUTION_DEMAND as tt, warmEvaluatedImports as u, emitOverlayLoaderInstall as ut, devBrowserSourceModuleUrl as v, resumeVirtualModuleId as vt, isPrerenderWakeSourceRequest as w, symbolVirtualModuleSourceFile as wt, executionLogRuntimeModuleId as x, settleVirtualModuleId as xt, devBrowserVirtualModuleUrl as y, rewriteSymbolModuleExport as yt, sourceForPrerenderWakeVirtualImporter as z };
@@ -55,6 +55,7 @@ interface TransformTsrxModuleInput {
55
55
  importedModuleInterfaces?: SemanticGraphInput['importedModuleInterfaces'];
56
56
  importedModuleConstants?: SemanticGraphInput['importedModuleConstants'];
57
57
  serverOnlyProps?: SemanticGraphInput['serverOnlyProps'];
58
+ routeRoot?: SemanticGraphInput['routeRoot'];
58
59
  renderDataImportSources?: Readonly<Record<string, string>>;
59
60
  artifactChildMaterializations?: Readonly<Record<string, ArtifactChildMaterialization>>;
60
61
  symbols?: import('@markless/compiler').SymbolResolverModuleInput['symbols'];
@@ -186,6 +187,8 @@ type MarklessRolldownPluginApi = {
186
187
  enableChunkImportMap: () => void;
187
188
  /** A host plugin names, per root-relative module id, the props browser code must never read. */
188
189
  declareServerOnlyProps: (resolve: (moduleId: string) => SemanticGraphInput['serverOnlyProps']) => void;
190
+ /** A host plugin names, per root-relative module id, the modules it renders as pages. */
191
+ declareRouteModules: (isRoute: (moduleId: string) => boolean) => void;
189
192
  invalidateGeneratedModules: (parent: string, environment?: MarklessEnvironment, nextSource?: string) => string[] | Promise<string[]>;
190
193
  runtimeDemandMaps: () => Iterable<RuntimeDemandMapManifest | undefined>;
191
194
  runtimeDemandSources: () => Iterable<{
package/dist/vite.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { c as MarklessEnvironment, g as PreloadGraphEntriesAdder, h as PreloadGraphEntries, i as MarklessBuildMetadata, l as MarklessManifest, m as PreloadGraphContext, n as GlobalInjections, t as BundleGraphAdder, u as MarklessRolldownOptions } from "./types-BqSoEVp6.js";
1
+ import { c as MarklessEnvironment, g as PreloadGraphEntriesAdder, h as PreloadGraphEntries, i as MarklessBuildMetadata, l as MarklessManifest, m as PreloadGraphContext, n as GlobalInjections, t as BundleGraphAdder, u as MarklessRolldownOptions } from "./types-iOUoceJ-.js";
2
2
  import { Plugin } from "vite";
3
3
  //#region src/vite/index.d.ts
4
4
  export interface MarklessViteOptions extends MarklessRolldownOptions {
package/dist/vite.js CHANGED
@@ -1,10 +1,10 @@
1
- import { c as renderMarklessDevErrorDocument, n as MARKLESS_DEV_ERROR_CLIENT_ID, r as MARKLESS_DEV_ERROR_EVENT, s as normalizeMarklessDevError, t as MARKLESS_DEV_ERROR_CLEAR_EVENT } from "./dev-error-DRvO28Fd.js";
2
- import { Et as executionLogActivationInjection, I as sharedReachedRenderDataRequest, at as STORAGE_FREE_RESUME_ENTRY_SPECIFIER, it as RESUME_ENTRY_SPECIFIER, j as pathname, nt as outputDefaults, t as MARKLESS_DEFERRED_PACK } from "./route-pack-groups-BpefyjrE.js";
1
+ import { a as MARKLESS_DEV_RELOADS_EVENT, i as MARKLESS_DEV_RELOADS_ATTRIBUTE, l as normalizeMarklessDevError, n as MARKLESS_DEV_ERROR_CLIENT_ID, r as MARKLESS_DEV_ERROR_EVENT, t as MARKLESS_DEV_ERROR_CLEAR_EVENT, u as renderMarklessDevErrorDocument } from "./dev-error-2hi-Icjn.js";
2
+ import { N as pathname, R as sharedReachedRenderDataRequest, at as outputDefaults, ct as STORAGE_FREE_RESUME_ENTRY_SPECIFIER, kt as executionLogActivationInjection, st as RESUME_ENTRY_SPECIFIER, t as MARKLESS_DEFERRED_PACK } from "./route-pack-groups-BXc755qH.js";
3
3
  import { n as includeOptimizedDeps, t as excludeSourceShippedDeps } from "./optimized-deps-BfzxSm6C.js";
4
- import { A as inlineDeferSource, E as preflightTsrxModuleDiagnostics, O as INLINE_DEFER_LOADER_SOURCE, T as prefetchChunkParses, _ as createPreloadGraphAdder, a as collapseInitFacadeImports, d as nativePackingEnabled, f as nativePackingPlugins, h as withUndemandedReExportDoors, k as createInlineDeferTriggerSource, l as marklessRuntimeSpecifierId, m as undemandedRuntimeModules, o as unwrapAsyncImportWrappers, p as isReExportDoor, t as createMarklessRolldownPlugin, u as DEPRECATED_NATIVE_PACKING_WARNING, v as runtimeModuleIdFromOrigin } from "./rolldown-BciZw5hZ.js";
4
+ import { A as createInlineDeferTriggerSource, D as preflightTsrxModuleDiagnostics, E as prefetchChunkParses, _ as createPreloadGraphAdder, a as collapseInitFacadeImports, d as nativePackingEnabled, f as nativePackingPlugins, h as withUndemandedReExportDoors, j as inlineDeferSource, k as INLINE_DEFER_LOADER_SOURCE, l as marklessRuntimeSpecifierId, m as undemandedRuntimeModules, o as unwrapAsyncImportWrappers, p as isReExportDoor, t as createMarklessRolldownPlugin, u as DEPRECATED_NATIVE_PACKING_WARNING, v as runtimeModuleIdFromOrigin } from "./rolldown-DHkCX7vL.js";
5
5
  import { n as marklessRosterPositions, r as marklessRosterRenderContext, t as marklessRosterPositionSeeds } from "./shared-seed-slot-ihIVCD2S.js";
6
6
  import { joinURL, parsePath, withQuery } from "ufo";
7
- import { ASYNC_PROTOCOL_VERSION, STORAGE_SLOT_SYMBOL_KEY, escapeScriptJson, serializeRuntimeAsyncSnapshots, serializeRuntimeStateCells, storageAttributeName, storageCookieName, storageSlotEntryKeyFromGraphNodeId } from "@markless/serializer";
7
+ import { ASYNC_PROTOCOL_VERSION, PROTOCOL_CONTAINER_HOST_NODE_ID, STORAGE_SLOT_SYMBOL_KEY, escapeScriptJson, serializeRuntimeAsyncSnapshots, serializeRuntimeStateCells, storageAttributeName, storageCookieName, storageSlotEntryKeyFromGraphNodeId } from "@markless/serializer";
8
8
  import { isAbsolute, join, resolve } from "pathe";
9
9
  import { DEBUGGING_PLAYBOOK_HINT } from "@markless/compiler";
10
10
  import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
@@ -12,26 +12,30 @@ import { isAbsolute as isAbsolute$1 } from "node:path";
12
12
  import { pathToFileURL } from "node:url";
13
13
  import { createServerModuleRunner, isRunnableDevEnvironment } from "vite";
14
14
  import { tmpdir } from "node:os";
15
- import { PROTOCOL_EVENT_ACTION_KIND as PROTOCOL_EVENT_ACTION_KIND$1, PROTOCOL_IDLE_EVENT_NAME as PROTOCOL_IDLE_EVENT_NAME$1, PROTOCOL_LOCATOR_PATHS_ATTRIBUTE, PROTOCOL_VISIBLE_EVENT_NAME, protocolEventDispatchesMarkless } from "@markless/serializer/protocol";
15
+ import { PROTOCOL_CONTAINER_END_COMMENT, PROTOCOL_CONTAINER_START_COMMENT, PROTOCOL_EVENT_ACTION_KIND as PROTOCOL_EVENT_ACTION_KIND$1, PROTOCOL_IDLE_EVENT_NAME as PROTOCOL_IDLE_EVENT_NAME$1, PROTOCOL_LOCATOR_PATHS_ATTRIBUTE, PROTOCOL_VISIBLE_EVENT_NAME, protocolEventDispatchesMarkless } from "@markless/serializer/protocol";
16
16
  import "@markless/serializer/resume-record-delta";
17
17
  //#region ../web/src/inline/served-census.ts
18
18
  /**
19
- * Pins the container's elements in DOM order as its census and returns them.
20
- * When the count differs from the one the server measured, a script outside
21
- * Markless changed the page first: the root is flagged for the resume module
22
- * to renumber the census, and no elements are returned, so nothing is matched
23
- * by a shifted index.
19
+ * Pins the container's elements in DOM order as its census and returns them,
20
+ * between the page start and end markers an author's element carries. When the
21
+ * count differs from the one the server measured, a script outside Markless
22
+ * changed the page first: the root is flagged for the resume module to renumber
23
+ * the census, and no elements are returned, so nothing is matched by a shifted index.
24
24
  */
25
25
  function marklessServedCensus(root, attribute) {
26
26
  const live = [root];
27
- const walker = document.createTreeWalker(root, 1);
28
- for (let next = walker.nextNode(); next; next = walker.nextNode()) live.push(next);
27
+ const walker = document.createTreeWalker(root, 129);
28
+ for (let next = walker.nextNode(); next; next = walker.nextNode()) if (next.nodeType !== 8) live.push(next);
29
+ else if (next.data === __MARKLESS_PAGE_START__) live.length = 1;
30
+ else if (next.data === __MARKLESS_PAGE_END__) break;
29
31
  root.__marklessCensus ||= live;
30
32
  const value = root.getAttribute?.(attribute);
31
33
  return value && parseInt(value) !== live.length ? (root.__marklessShifted = 1, []) : live;
32
34
  }
33
35
  //#endregion
34
36
  //#region ../web/src/inline/resumer.ts
37
+ const withPageMarkers = (source) => source.replaceAll("__MARKLESS_PAGE_START__", JSON.stringify(PROTOCOL_CONTAINER_START_COMMENT)).replaceAll("__MARKLESS_PAGE_END__", JSON.stringify(PROTOCOL_CONTAINER_END_COMMENT));
38
+ const servedCensusSource = () => withPageMarkers(marklessServedCensus.toString());
35
39
  PROTOCOL_EVENT_ACTION_KIND$1.event, PROTOCOL_EVENT_ACTION_KIND$1.externalDelegate;
36
40
  const INLINE_MODULE_LOADER_SOURCE = INLINE_DEFER_LOADER_SOURCE;
37
41
  function createInlineResumerSelfWakeSource(resumeModuleUrl) {
@@ -54,14 +58,14 @@ function runInlineResumerStorageWake(slotSymbolKey, rendered, wake) {
54
58
  * with no mark ships a byte-identical resumer.
55
59
  */
56
60
  function createInlineResumerOverlayPrimerSource(resumeModuleUrl) {
57
- return `;(${runInlineResumerOverlayPrimer.toString()})(${JSON.stringify(resumeModuleUrl)},${INLINE_MODULE_LOADER_SOURCE});`;
61
+ return `;(${withPageMarkers(runInlineResumerOverlayPrimer.toString())})(${JSON.stringify(resumeModuleUrl)},${INLINE_MODULE_LOADER_SOURCE});`;
58
62
  }
59
63
  const PRERENDER_INLINE_EVENT_NAMES_TOKEN = "__MARKLESS_PRERENDER_EVENT_NAMES__";
60
64
  function renderPrerenderInlineResumerSource(compiled, eventNames) {
61
65
  return compiled.replace(PRERENDER_INLINE_EVENT_NAMES_TOKEN, JSON.stringify(eventNames));
62
66
  }
63
67
  function createPrerenderInlineResumerSource(eventNames, resumeModuleUrl, options) {
64
- const plain = `(${runPrerenderInlineResumer.toString()})(${JSON.stringify(eventNames)},${JSON.stringify(resumeModuleUrl)},u=>import(u),${marklessServedCensus.toString()},${JSON.stringify(PROTOCOL_LOCATOR_PATHS_ATTRIBUTE)});`;
68
+ const plain = `(${runPrerenderInlineResumer.toString()})(${JSON.stringify(eventNames)},${JSON.stringify(resumeModuleUrl)},u=>import(u),${servedCensusSource()},${JSON.stringify(PROTOCOL_LOCATOR_PATHS_ATTRIBUTE)});`;
65
69
  const logging = options?.executionLog !== void 0 && options.executionLog !== "never";
66
70
  if (!options?.debug && !logging) return plain;
67
71
  return `{
@@ -174,7 +178,7 @@ function runInlineResumerSelfWake(fallbackResumeModuleUrl, loadModule, defer) {
174
178
  defer.idle(root, async () => {
175
179
  if (root.__asyncResumeRuntimeStarted) return;
176
180
  root.__marklessDelegatedDispatch = true;
177
- await (await loadModule(resumeModuleUrl)).resumeContainerEvent({
181
+ await (await (root.__mResume ||= loadModule(resumeModuleUrl))).resumeContainerEvent({
178
182
  root,
179
183
  event: 0
180
184
  });
@@ -196,8 +200,10 @@ function runInlineResumerOverlayPrimer(fallbackResumeModuleUrl, loadModule) {
196
200
  if (root.__marklessDelegatedDispatch === true) return;
197
201
  if (!root.__marklessCensus) {
198
202
  const census = [root];
199
- const all = root.getElementsByTagName?.("*") ?? [];
200
- for (let index = 0; index < all.length; index++) census.push(all[index]);
203
+ const walker = document.createTreeWalker(root, 129);
204
+ for (let next = walker.nextNode(); next; next = walker.nextNode()) if (next.nodeType !== 8) census.push(next);
205
+ else if (next.data === __MARKLESS_PAGE_START__) census.length = 1;
206
+ else if (next.data === __MARKLESS_PAGE_END__) break;
201
207
  root.__marklessCensus = census;
202
208
  }
203
209
  setTimeout(() => {
@@ -232,12 +238,19 @@ async function prepareSsrResumeRecords(output) {
232
238
  };
233
239
  }
234
240
  function containerScopedView(view) {
241
+ const locators = view.locators.map((locator) => ({
242
+ ...locator,
243
+ index: locator.index + 1
244
+ }));
245
+ if (view.keyedRepeats?.some((repeat) => repeat.parentHostNodeId === PROTOCOL_CONTAINER_HOST_NODE_ID)) locators.unshift({
246
+ hostNodeId: PROTOCOL_CONTAINER_HOST_NODE_ID,
247
+ strategy: "dom-order",
248
+ index: 0,
249
+ tagName: "*"
250
+ });
235
251
  return {
236
252
  ...view,
237
- locators: view.locators.map((locator) => ({
238
- ...locator,
239
- index: locator.index + 1
240
- }))
253
+ locators
241
254
  };
242
255
  }
243
256
  function emptyStatePayload() {
@@ -259,6 +272,9 @@ function emptyViewPayload() {
259
272
  };
260
273
  }
261
274
  //#endregion
275
+ //#region ../web/src/fns/container-region.ts
276
+ const CONTAINER_ATTRIBUTE = "data-async-container";
277
+ //#endregion
262
278
  //#region ../web/src/fns/roster-position.ts
263
279
  /**
264
280
  * The server render context with the roster channels on it. One counter per
@@ -485,7 +501,7 @@ async function assemblePrerenderPageParts(component, output, options) {
485
501
  const { state, view } = await prepareSsrResumeRecords(output);
486
502
  const browserTriggers = hasBrowserTriggers(view, state);
487
503
  const resumeModuleUrl = options.prerenderWakeModuleUrl ?? options.resumeModuleUrl ?? artifactPrerenderWakeModuleUrl(component) ?? artifactResumeModuleUrl(component);
488
- const modulePreloads = (typeof options.modulePreloads === "function" ? options.modulePreloads(output.html) : options.modulePreloads) ?? (browserTriggers ? artifactModulePreloads(component) : void 0);
504
+ const modulePreloads = (typeof options.modulePreloads === "function" ? options.modulePreloads(output.html, browserTriggers && resumeModuleUrl !== void 0) : options.modulePreloads) ?? (browserTriggers ? artifactModulePreloads(component) : void 0);
489
505
  const eventNames = browserEventNames(view);
490
506
  const selfWake = hasUnsettledAsyncBoundaryRunner(view, state);
491
507
  const boot = artifactPrerenderBoot(component);
@@ -656,25 +672,34 @@ function eventHostIndexes(view, eventName) {
656
672
  function deferredTriggerSource(view) {
657
673
  const visible = eventHostIndexes(view, PROTOCOL_VISIBLE_EVENT_NAME);
658
674
  const idle = eventHostIndexes(view, PROTOCOL_IDLE_EVENT_NAME$1);
659
- if (browserEventNames({
675
+ const nested = deferredEventNames({
660
676
  ...view,
661
677
  events: []
662
- }).includes(PROTOCOL_IDLE_EVENT_NAME$1)) idle.push(0);
678
+ });
679
+ if (nested.includes(PROTOCOL_VISIBLE_EVENT_NAME)) visible.push(0);
680
+ if (nested.includes(PROTOCOL_IDLE_EVENT_NAME$1)) idle.push(0);
663
681
  return (visible.length > 0 ? createInlineDeferTriggerSource("visible", visible) : "") + (idle.length > 0 ? createInlineDeferTriggerSource("idle", idle) : "");
664
682
  }
665
683
  function browserEventNames(view) {
684
+ return deferredEventNames(view).filter((eventName) => eventName !== PROTOCOL_VISIBLE_EVENT_NAME);
685
+ }
686
+ function deferredEventNames(view) {
666
687
  return [.../* @__PURE__ */ new Set([
667
688
  ...view.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName),
668
689
  ...(view.keyedRepeats ?? []).flatMap((repeat) => repeat.rowEvents.map((event) => event.eventName)),
669
690
  ...(view.branches ?? []).flatMap((branch) => [...(branch.armRecords ?? []).flatMap((arm) => arm.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName)), ...branchServedArmEventNames(branch)]),
670
691
  ...view.asyncBoundaries.flatMap(boundaryArmEventNames)
671
- ])].filter((eventName) => eventName !== PROTOCOL_VISIBLE_EVENT_NAME);
692
+ ])];
672
693
  }
673
694
  function renderContainer(containerId, parts, locators) {
674
695
  const inner = parts.filter(Boolean).join("");
675
696
  const paths = servedLocatorPaths(inner, locators);
676
- return `<div data-async-container${containerId ? `="${escapeAttribute(containerId)}"` : ""}${paths ? ` ${PROTOCOL_LOCATOR_PATHS_ATTRIBUTE}="${paths}"` : ""}>${inner}</div>`;
697
+ const id = containerId ? `="${escapeAttribute(containerId)}"` : "";
698
+ const located = paths ? ` ${PROTOCOL_LOCATOR_PATHS_ATTRIBUTE}="${paths}"` : "";
699
+ return `${CONTAINER_OPEN}${id}${located}>${inner}${CONTAINER_CLOSE}`;
677
700
  }
701
+ const CONTAINER_OPEN = `<div ${CONTAINER_ATTRIBUTE}`;
702
+ const CONTAINER_CLOSE = "</div>";
678
703
  function renderInlineResumerScript(source, nonce, resumeModuleUrl, selfWake, settleModuleUrl, appendSelfWakeSource = true, overlayPrimer = false, appendedSource = "", deferFactory) {
679
704
  const nonceAttribute = nonce ? ` nonce="${escapeAttribute(nonce)}"` : "";
680
705
  const resumeModuleAttribute = resumeModuleUrl ? ` data-markless-resume-module="${escapeAttribute(resumeModuleUrl)}"` : "";
@@ -1327,6 +1352,8 @@ function createDevErrorClientAsset(viteClientUrl) {
1327
1352
  const hot = createHotContext(${JSON.stringify(MARKLESS_DEV_ERROR_CLIENT_ID)});
1328
1353
  const ERROR_EVENT = ${JSON.stringify(MARKLESS_DEV_ERROR_EVENT)};
1329
1354
  const CLEAR_EVENT = ${JSON.stringify(MARKLESS_DEV_ERROR_CLEAR_EVENT)};
1355
+ const RELOADS_EVENT = ${JSON.stringify(MARKLESS_DEV_RELOADS_EVENT)};
1356
+ const RELOADS_ATTRIBUTE = ${JSON.stringify(MARKLESS_DEV_RELOADS_ATTRIBUTE)};
1330
1357
  const ELEMENT = 'markless-dev-error-overlay';
1331
1358
  const SUPPRESSION = 'data-markless-vite-overlay-suppression';
1332
1359
  const OPEN_IN_EDITOR = ${JSON.stringify(`${base}/__open-in-editor`)};
@@ -1400,6 +1427,8 @@ hot.on(CLEAR_EVENT, ({ id }) => { if (currentPayload?.id === id) reset(); });
1400
1427
  hot.on('vite:beforeFullReload', reset);
1401
1428
  addEventListener('keydown', (event) => { if (event.key === 'Escape') document.querySelector(ELEMENT)?.remove(); });
1402
1429
  if (window.__MARKLESS_DEV_ERROR__) show(window.__MARKLESS_DEV_ERROR__);
1430
+ const servedAfter = document.querySelector('script[' + RELOADS_ATTRIBUTE + ']')?.getAttribute(RELOADS_ATTRIBUTE);
1431
+ if (servedAfter != null) hot.send(RELOADS_EVENT, { reloads: Number(servedAfter) });
1403
1432
  `;
1404
1433
  }
1405
1434
  //#endregion
@@ -1464,6 +1493,13 @@ function createViteHmr(options) {
1464
1493
  let recheckingInvalidSources = false;
1465
1494
  const preflightByFile = /* @__PURE__ */ new Map();
1466
1495
  const unreportedInvalidations = /* @__PURE__ */ new Map();
1496
+ let editReloads = 0;
1497
+ let lastReloadedEdit;
1498
+ function countEditReload(edit) {
1499
+ if (edit === lastReloadedEdit) return;
1500
+ lastReloadedEdit = edit;
1501
+ editReloads += 1;
1502
+ }
1467
1503
  let hotUpdatePasses = 0;
1468
1504
  let hotUpdateCycle;
1469
1505
  function beginHotUpdatePass() {
@@ -1587,7 +1623,10 @@ function createViteHmr(options) {
1587
1623
  sendClear(id);
1588
1624
  recovered = true;
1589
1625
  }
1590
- if (recovered) server?.environments?.[options.clientEnvironment]?.hot?.send?.({ type: "full-reload" });
1626
+ if (recovered) {
1627
+ countEditReload(`recovered\0${Date.now()}`);
1628
+ server?.environments?.[options.clientEnvironment]?.hot?.send?.({ type: "full-reload" });
1629
+ }
1591
1630
  } finally {
1592
1631
  recheckingInvalidSources = false;
1593
1632
  stopInvalidSourceRecheckIfIdle();
@@ -1612,7 +1651,15 @@ function createViteHmr(options) {
1612
1651
  installServerRenderBarrier(nextServer);
1613
1652
  nextServer.httpServer?.once("close", cleanup);
1614
1653
  nextServer.watcher?.once?.("close", cleanup);
1615
- if (options.enabled) installFetchViteClient(nextServer, options);
1654
+ if (options.enabled) {
1655
+ installFetchViteClient(nextServer, options, async () => {
1656
+ await settledHotUpdate();
1657
+ return editReloads;
1658
+ });
1659
+ nextServer.environments?.[options.clientEnvironment]?.hot?.on?.(MARKLESS_DEV_RELOADS_EVENT, (data, client) => {
1660
+ if (data?.reloads !== editReloads) client.send({ type: "full-reload" });
1661
+ });
1662
+ }
1616
1663
  },
1617
1664
  transformIndexHtml() {},
1618
1665
  resolveId(id) {
@@ -1641,6 +1688,17 @@ function createViteHmr(options) {
1641
1688
  }
1642
1689
  }
1643
1690
  };
1691
+ function loadedOrInvalid(environments, file) {
1692
+ const path = parsePath(file).pathname;
1693
+ if (invalidSources.has(path)) return true;
1694
+ let answered = false;
1695
+ for (const environment of environments) {
1696
+ if (typeof environment.moduleGraph?.getModulesByFile !== "function") continue;
1697
+ answered = true;
1698
+ if (environment.moduleGraph.getModulesByFile(path)?.size) return true;
1699
+ }
1700
+ return !answered;
1701
+ }
1644
1702
  async function runHotUpdate(environment, ctx) {
1645
1703
  if (!environment) return;
1646
1704
  const env = marklessEnvironment(environment);
@@ -1659,6 +1717,7 @@ function createViteHmr(options) {
1659
1717
  }
1660
1718
  const modules = new Set(ctx.modules ?? []);
1661
1719
  if (ctx.file) for (const target of targets.keys()) for (const module of target.moduleGraph?.getModulesByFile?.(ctx.file) ?? []) modules.add(module);
1720
+ if (modules.size === 0 && ctx.file && !loadedOrInvalid(targets.keys(), ctx.file)) return [];
1662
1721
  const files = changedFiles([...modules]);
1663
1722
  const root = server?.config?.root;
1664
1723
  if (ctx.file && SOURCE_FILE_EXTENSION.test(ctx.file)) {
@@ -1722,6 +1781,7 @@ function createViteHmr(options) {
1722
1781
  recordUnreportedInvalidation(targetEnvironment, invalidated);
1723
1782
  }
1724
1783
  reloadModuleRunner();
1784
+ countEditReload(`${ctx.file}\0${ctx.timestamp}`);
1725
1785
  hot.send({
1726
1786
  type: "full-reload",
1727
1787
  path: firstChangedFile(files),
@@ -1737,16 +1797,17 @@ async function fetchedModuleNode(environment, id) {
1737
1797
  function hasErrorCode(error, code) {
1738
1798
  return typeof error === "object" && error !== null && "code" in error && error.code === code;
1739
1799
  }
1740
- function installFetchViteClient(server, options) {
1800
+ function installFetchViteClient(server, options, servedAfterReloads) {
1741
1801
  for (const environment of Object.values(server.environments)) {
1742
1802
  const fetchEnv = fetchableDevEnvironment(environment);
1743
1803
  if (!fetchEnv) continue;
1744
1804
  const dispatchFetch = fetchEnv.dispatchFetch.bind(fetchEnv);
1745
1805
  fetchEnv.dispatchFetch = async (request) => {
1806
+ const reloads = await servedAfterReloads();
1746
1807
  const response = await dispatchFetch(request);
1747
1808
  if (!response.headers.get("content-type")?.includes("text/html")) return response;
1748
1809
  const html = await response.text();
1749
- const nextHtml = injectDevClients(html, options.base);
1810
+ const nextHtml = injectDevClients(html, options.base, reloads);
1750
1811
  const headers = new Headers(response.headers);
1751
1812
  if (nextHtml !== html) headers.delete("content-length");
1752
1813
  return new Response(nextHtml, {
@@ -1757,9 +1818,9 @@ function installFetchViteClient(server, options) {
1757
1818
  };
1758
1819
  }
1759
1820
  }
1760
- function injectDevClients(html, base) {
1821
+ function injectDevClients(html, base, reloads) {
1761
1822
  if (!html) return html;
1762
- const tags = [...html.includes("/@vite/client") ? [] : [`<script type="module" src="${joinURL(base, "/@vite/client")}"><\/script>`], ...html.includes("virtual:markless:dev-error-client") ? [] : [`<script type="module" src="${joinURL(base, `/@id/__x00__${MARKLESS_DEV_ERROR_CLIENT_ID}`)}"><\/script>`]].join("");
1823
+ const tags = [...html.includes("/@vite/client") ? [] : [`<script type="module" src="${joinURL(base, "/@vite/client")}"><\/script>`], ...html.includes("virtual:markless:dev-error-client") ? [] : [`<script type="module" src="${joinURL(base, `/@id/__x00__${MARKLESS_DEV_ERROR_CLIENT_ID}`)}"${reloads === void 0 ? "" : ` ${MARKLESS_DEV_RELOADS_ATTRIBUTE}="${reloads}"`}><\/script>`]].join("");
1763
1824
  if (!tags) return html;
1764
1825
  if (html.includes("</head>")) return html.replace("</head>", `${tags}</head>`);
1765
1826
  if (html.includes("<head>")) return html.replace("<head>", `<head>${tags}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markless/bundler",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Markless build plugins for Rolldown and Vite.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -39,12 +39,12 @@
39
39
  "@thi.ng/dgraph": "^2.1.205",
40
40
  "pathe": "^2.0.3",
41
41
  "ufo": "^1.6.4",
42
- "@markless/serializer": "0.5.0",
43
- "@markless/compiler": "0.5.0",
44
- "@markless/web": "0.5.0"
42
+ "@markless/compiler": "0.6.0",
43
+ "@markless/serializer": "0.6.0",
44
+ "@markless/web": "0.6.0"
45
45
  },
46
46
  "devDependencies": {
47
- "@markless/analyzer": "0.5.0"
47
+ "@markless/analyzer": "0.6.0"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "rolldown": "1.2.7",