@markless/bundler 0.6.0 → 0.8.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.
@@ -5,6 +5,7 @@ const MARKLESS_DEV_ERROR_CLEAR_EVENT = "markless:dev-error-clear";
5
5
  const MARKLESS_DEV_ERROR_CLIENT_ID = "virtual:markless:dev-error-client";
6
6
  const MARKLESS_DEV_RELOADS_EVENT = "markless:dev-reloads";
7
7
  const MARKLESS_DEV_RELOADS_ATTRIBUTE = "data-markless-dev-reloads";
8
+ const MARKLESS_DEV_PAGE_EDIT_EVENT = "markless:dev-page-edit";
8
9
  const PLUGIN_CODE_KIND = "markless-dev-error";
9
10
  const PLUGIN_CODE_VERSION = 1;
10
11
  var MarklessCompileError = class extends Error {
@@ -173,4 +174,4 @@ const documentStyles = `
173
174
  .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}
174
175
  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}`;
175
176
  //#endregion
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 };
177
+ export { MARKLESS_DEV_RELOADS_ATTRIBUTE as a, createCompileErrorPayload as c, renderMarklessDevErrorDocument as d, renderMarklessDevErrorPlainText as f, MARKLESS_DEV_PAGE_EDIT_EVENT as i, formatMarklessSourceFrame as l, MARKLESS_DEV_ERROR_CLIENT_ID as n, MARKLESS_DEV_RELOADS_EVENT as o, serializeMarklessDevError as p, MARKLESS_DEV_ERROR_EVENT as r, MarklessCompileError as s, MARKLESS_DEV_ERROR_CLEAR_EVENT as t, normalizeMarklessDevError as u };
@@ -5,6 +5,7 @@ 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
6
  export declare const MARKLESS_DEV_RELOADS_EVENT = "markless:dev-reloads";
7
7
  export declare const MARKLESS_DEV_RELOADS_ATTRIBUTE = "data-markless-dev-reloads";
8
+ export declare const MARKLESS_DEV_PAGE_EDIT_EVENT = "markless:dev-page-edit";
8
9
  export interface MarklessDevDiagnostic {
9
10
  readonly code: string;
10
11
  readonly message: string;
package/dist/dev-error.js CHANGED
@@ -1,2 +1 @@
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
+ export { t as MARKLESS_DEV_ERROR_CLEAR_EVENT, n as MARKLESS_DEV_ERROR_CLIENT_ID, r as MARKLESS_DEV_ERROR_EVENT, i as MARKLESS_DEV_PAGE_EDIT_EVENT, a as MARKLESS_DEV_RELOADS_ATTRIBUTE, o as MARKLESS_DEV_RELOADS_EVENT, s as MarklessCompileError, c as createCompileErrorPayload, l as formatMarklessSourceFrame, u as normalizeMarklessDevError, d as renderMarklessDevErrorDocument, f as renderMarklessDevErrorPlainText, p as serializeMarklessDevError } from "./dev-error-BEduK_R3.js";
package/dist/preload.js CHANGED
@@ -1,4 +1,4 @@
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";
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-BLS6xeVV.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 = {
@@ -1,11 +1,11 @@
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";
1
+ import { c as createCompileErrorPayload, s as MarklessCompileError } from "./dev-error-BEduK_R3.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-BLS6xeVV.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
6
  import { basename, dirname, extname, isAbsolute, join, normalize, relative, resolve } from "pathe";
7
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
- import { PRERENDER_INLINE_EVENT_NAMES_TOKEN, createInlineResumerDebugRegistrationSource, createInlineResumerSelfWakeSource, createInlineResumerSource, createPrerenderInlineResumerSource, createPrerenderSettleInlineResumerSource } from "@markless/web/inline/resumer";
8
+ import { INLINE_RESUMER_PAGE_TOKEN, PRERENDER_INLINE_EVENT_NAMES_TOKEN, createInlineResumerDebugRegistrationSource, createInlineResumerSelfWakeSource, createInlineResumerSource, createPrerenderInlineResumerSource, createPrerenderSettleInlineResumerSource } from "@markless/web/inline/resumer";
9
9
  import { parse, parseSync } from "rolldown/experimental";
10
10
  import { copyFile, mkdir, readFile, readdir, rename, rm, rmdir } from "node:fs/promises";
11
11
  import { defDGraph } from "@thi.ng/dgraph";
@@ -594,18 +594,33 @@ 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-event-host.ts
598
+ /**
599
+ * The attribute the server writes on each served element that hosts an event
600
+ * record. The inline boot reads it from the event target up, so it finds a
601
+ * press's handler and sync policy without parsing a payload or knowing the
602
+ * element's position. Grammar: entries joined by `;`, each
603
+ * `name[:ref][!policy]`, where `ref` is the record's index in its region's event
604
+ * list (or `-` for an event an external delegate owns) and `policy` is `p`, `s`,
605
+ * `ps` or an index into the container's sync-policy table.
606
+ */
607
+ const PROTOCOL_EVENT_HOST_ATTRIBUTE = "m:on";
608
+ //#endregion
597
609
  //#region ../serializer/src/protocol-page-markers.ts
598
610
  const PROTOCOL_CONTAINER_START_COMMENT = "markless:page-start";
599
611
  const PROTOCOL_CONTAINER_END_COMMENT = "markless:page-end";
600
612
  //#endregion
601
613
  //#region ../web/src/inline/defer.ts
614
+ const PROTOCOL_EVENT_HOST_SELECTOR = PROTOCOL_EVENT_HOST_ATTRIBUTE.replace(":", "\\:");
602
615
  /**
603
616
  * The one startup helper deferred triggers share. Serialized whole into a served
604
- * page that has one; a client mount and the runtime call it directly. Hosts come
605
- * from compiler-emitted DOM-order indexes, index 0 being the container itself,
606
- * which hands records the runtime owns (arms, rows) to the runtime.
617
+ * page that has one; a client mount and the runtime call it directly. Hosts are
618
+ * the elements whose event host attribute (`hostSelector`, escaped for a CSS
619
+ * attribute selector) names the lane's event with a record;
620
+ * `ownsRoot` adds the container itself, which hands records the runtime owns
621
+ * (arms, rows) to the runtime.
607
622
  */
608
- function createMarklessDefer(loadModule, pageStart, pageEnd, pathsAttribute) {
623
+ function createMarklessDefer(loadModule, pageStart, pageEnd, pathsAttribute, hostSelector) {
609
624
  const scope = globalThis;
610
625
  const clockOf = (root) => root.__mClock || {
611
626
  frame: (run) => requestAnimationFrame(run),
@@ -617,6 +632,14 @@ function createMarklessDefer(loadModule, pageStart, pageEnd, pathsAttribute) {
617
632
  for (let next = walker.nextNode(); next; next = walker.nextNode()) if (next.nodeType !== 8) live.push(next);
618
633
  else if (next.data === pageStart) live.length = 1;
619
634
  else if (next.data === pageEnd) break;
635
+ const paths = pathsAttribute && root.getAttribute?.(pathsAttribute);
636
+ const order = paths && paths.split("|")[3];
637
+ let signature = 0;
638
+ if (order) for (const element of live.slice(1)) {
639
+ const name = element.localName ?? element.tagName ?? "";
640
+ signature = signature * 31 + name.length * 32 + (name.charCodeAt(0) | 32) | 0;
641
+ }
642
+ if (paths && (parseInt(paths) !== live.length || order && order !== (signature >>> 0).toString(36))) root.__marklessShifted = 1;
620
643
  return live;
621
644
  };
622
645
  const idle = (root, run) => {
@@ -626,7 +649,7 @@ function createMarklessDefer(loadModule, pageStart, pageEnd, pathsAttribute) {
626
649
  if (document.readyState === "complete") loaded();
627
650
  else addEventListener("load", loaded, { once: true });
628
651
  };
629
- const trigger = (target, lane, hostIndexes, eventName) => {
652
+ const trigger = (target, lane, ownsRoot, eventName) => {
630
653
  const root = target;
631
654
  const url = document.currentScript?.getAttribute("data-markless-resume-module");
632
655
  if (!root || !url) return;
@@ -657,13 +680,8 @@ function createMarklessDefer(loadModule, pageStart, pageEnd, pathsAttribute) {
657
680
  if (!--pending && root.__marklessDelegatedDispatch === eventName) root.__marklessDelegatedDispatch = void 0;
658
681
  });
659
682
  };
660
- const all = root.__marklessCensus ?? census(root);
661
- const paths = pathsAttribute && root.getAttribute?.(pathsAttribute);
662
- if (paths && parseInt(paths) !== all.length) root.__marklessShifted = 1;
663
- const hosts = root.__marklessShifted ? [root] : hostIndexes.flatMap((index) => {
664
- const host = all[index];
665
- return host ? [host] : [];
666
- });
683
+ const hosts = ownsRoot ? [root] : [];
684
+ hosts.push(...root.querySelectorAll(`[${hostSelector}^="${eventName}:"],[${hostSelector}*=";${eventName}:"]`));
667
685
  if (lane === "idle") return idle(root, () => hosts.forEach(claim));
668
686
  const observer = new IntersectionObserver((entries) => {
669
687
  for (const entry of entries) if (entry.isIntersecting) {
@@ -678,12 +696,12 @@ function createMarklessDefer(loadModule, pageStart, pageEnd, pathsAttribute) {
678
696
  const INLINE_DEFER_LOADER_SOURCE = "(url) => import(/* @vite-ignore */ url)";
679
697
  /** An expression that installs the helper once per document and evaluates to it; a build passes the factory minified. */
680
698
  function inlineDeferSource(factory = createMarklessDefer.toString()) {
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)}))`;
699
+ 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)},${JSON.stringify(PROTOCOL_EVENT_HOST_SELECTOR)}))`;
682
700
  }
683
701
  /** One lane's registration, appended only to a served page whose records name that lane's event. */
684
- function createInlineDeferTriggerSource(lane, hostIndexes) {
702
+ function createInlineDeferTriggerSource(lane, ownsRoot) {
685
703
  const eventName = lane === "idle" ? PROTOCOL_IDLE_EVENT_NAME$1 : PROTOCOL_VISIBLE_EVENT_NAME;
686
- return `;${inlineDeferSource()}(document.currentScript?.closest('[data-async-container]'),${JSON.stringify(lane)},${JSON.stringify(hostIndexes)},${JSON.stringify(eventName)});`;
704
+ return `;${inlineDeferSource()}(document.currentScript?.closest('[data-async-container]'),${JSON.stringify(lane)},${ownsRoot ? 1 : 0},${JSON.stringify(eventName)});`;
687
705
  }
688
706
  //#endregion
689
707
  //#region src/inline-resumer.ts
@@ -786,7 +804,9 @@ async function compileInlineResumerSource(options) {
786
804
  module: false
787
805
  });
788
806
  assertOxcResult("minify", minified.errors);
789
- return minified.code.trim();
807
+ const code = minified.code.trim();
808
+ if (!code.includes(INLINE_RESUMER_PAGE_TOKEN)) throw new Error("MARKLESS_INLINE_RESUMER_PAGE_TOKEN_FOLDED");
809
+ return code;
790
810
  }
791
811
  function assertOxcResult(phase, errors) {
792
812
  if (errors.length === 0) return;
@@ -2346,6 +2366,18 @@ function* bundleGraphEdges(graph) {
2346
2366
  function normalizeManifestOrigin(origin) {
2347
2367
  return withoutLeadingSlash(normalize(origin));
2348
2368
  }
2369
+ function entryReachableModuleIds(context) {
2370
+ const ids = [...context.getModuleIds()];
2371
+ const reached = /* @__PURE__ */ new Set();
2372
+ const pending = ids.filter((id) => context.getModuleInfo(id)?.isEntry);
2373
+ for (let id = pending.pop(); id !== void 0; id = pending.pop()) {
2374
+ if (reached.has(id)) continue;
2375
+ reached.add(id);
2376
+ const info = context.getModuleInfo(id);
2377
+ if (info) pending.push(...info.importedIds, ...info.dynamicallyImportedIds);
2378
+ }
2379
+ return ids.filter((id) => reached.has(id));
2380
+ }
2349
2381
  //#endregion
2350
2382
  //#region src/build/byte-attribution.ts
2351
2383
  const BYTE_CATEGORY = {
@@ -3159,8 +3191,7 @@ function planShortExportNames(chunks) {
3159
3191
  return true;
3160
3192
  }, strings);
3161
3193
  }
3162
- const text = strings.join("\n");
3163
- for (const chunk of chunks) if (text.includes(chunk.fileName.slice(chunk.fileName.lastIndexOf("/") + 1))) escaping.add(chunk.fileName);
3194
+ for (const fileName of namedInStrings(strings, chunks.map((chunk) => chunk.fileName))) escaping.add(fileName);
3164
3195
  const renames = /* @__PURE__ */ new Map();
3165
3196
  const pruned = /* @__PURE__ */ new Map();
3166
3197
  const finalNames = /* @__PURE__ */ new Map();
@@ -3235,6 +3266,19 @@ function planShortExportNames(chunks) {
3235
3266
  exports: new Map([...finalNames].map(([fileName, list]) => [fileName, list.filter((name) => !pruned.get(fileName)?.has(name)).map((name) => renames.get(fileName)?.get(name) ?? name)]))
3236
3267
  };
3237
3268
  }
3269
+ function namedInStrings(strings, fileNames) {
3270
+ const texts = /* @__PURE__ */ new Map();
3271
+ return fileNames.filter((fileName) => {
3272
+ const base = fileName.slice(fileName.lastIndexOf("/") + 1);
3273
+ const extension = base.includes(".") ? base.slice(base.lastIndexOf(".")) : "";
3274
+ let text = texts.get(extension);
3275
+ if (text === void 0) {
3276
+ text = strings.filter((value) => value.includes(extension)).join("\n");
3277
+ texts.set(extension, text);
3278
+ }
3279
+ return text.includes(base);
3280
+ });
3281
+ }
3238
3282
  /** Deterministic: each name is the shortest prefix of its own hash that no other name in the set shares. */
3239
3283
  function shortNames(names, taken = /* @__PURE__ */ new Set()) {
3240
3284
  const hashes = [...new Set(names)].map((name) => [name, identifierHash(name)]);
@@ -4193,7 +4237,7 @@ function nativePackingPlugins(root, demandMaps = () => [], demandSources = () =>
4193
4237
  const routeSources = /* @__PURE__ */ new Set();
4194
4238
  const entrySources = /* @__PURE__ */ new Set();
4195
4239
  const entryIds = /* @__PURE__ */ new Set();
4196
- for (const id of this.getModuleIds()) {
4240
+ for (const id of entryReachableModuleIds(this)) {
4197
4241
  const info = this.getModuleInfo(id);
4198
4242
  if (!info || "isExternal" in info && info.isExternal) continue;
4199
4243
  const handlerSource = sourceForSymbolVirtualImporter(id);
@@ -4548,7 +4592,9 @@ async function resolveImportedChildren(context, parent, manifest, fallbackSource
4548
4592
  }
4549
4593
  async function forceImportedModules(context, children, moduleArtifacts, metadata, options, environment) {
4550
4594
  for (const child of children) {
4551
- const loadSource = linkedModuleLoadSource(child, moduleArtifacts.has(child.source));
4595
+ const artifact = moduleArtifacts.get(child.source);
4596
+ const pendingRequest = options.dev === true || metadata.waitsOn(environment, child.source, pathname$1(child.parent)) ? void 0 : artifact?.provisionalUntil;
4597
+ const loadSource = linkedModuleLoadSource(child, artifact !== void 0 && pendingRequest === void 0) && (pendingRequest ?? child.source);
4552
4598
  if (loadSource !== void 0) await metadata.whileWaiting(environment, pathname$1(child.parent), child.source, async () => {
4553
4599
  if (options.dev === true) await options.devServer?.transformRequest(loadSource, environment);
4554
4600
  else if (typeof context.load === "function") await context.load({ id: loadSource });
@@ -4672,6 +4718,16 @@ function moduleLinkArtifact(result) {
4672
4718
  delegateChildren: delegateChildResolutionRequests(result.artifactChildren).length > 0
4673
4719
  };
4674
4720
  }
4721
+ function publishModuleLinkArtifact(artifacts, source, artifact, options) {
4722
+ const current = artifacts.get(source);
4723
+ if (options.provisionalUntil !== void 0) {
4724
+ if (!options.dev && current && current.provisionalUntil === void 0) return;
4725
+ artifacts.set(source, {
4726
+ ...artifact,
4727
+ provisionalUntil: options.provisionalUntil
4728
+ });
4729
+ } else artifacts.set(source, artifact);
4730
+ }
4675
4731
  async function materializeDelegateChildren(context, parent, candidates, options = {}) {
4676
4732
  const resolution = {};
4677
4733
  for (const candidate of delegateChildResolutionRequests(candidates)) {
@@ -5220,7 +5276,7 @@ function registerTransformArtifacts(state, input) {
5220
5276
  const stored = {
5221
5277
  ...module,
5222
5278
  ...isClientSymbol ? { source: requalifyExecutionLogModuleHook(module.source, logId) } : {},
5223
- ...input.finalPublication === false && (module.type === "resolver" || module.type === "symbol") ? { provisional: true } : {}
5279
+ ...input.finalPublication === false && (module.type === "resolver" || module.type === "symbol" || module.type === "render-data" && input.devServer !== true) ? { provisional: true } : {}
5224
5280
  };
5225
5281
  const published = publishesVirtualModule(stored, state.virtualModules.get(module.id));
5226
5282
  if (published) state.virtualModules.set(module.id, stored);
@@ -5253,7 +5309,10 @@ function registerTransformArtifacts(state, input) {
5253
5309
  });
5254
5310
  if (input.tracksSourceClaimPublication === true) state.moduleMetadata.finishSourceSymbolClaims(input.environment, input.source, input.manifestSource);
5255
5311
  }
5256
- state.moduleLinkArtifacts(input.environment).set(input.source, moduleLinkArtifact(input.result));
5312
+ publishModuleLinkArtifact(state.moduleLinkArtifacts(input.environment), input.source, moduleLinkArtifact(input.result), {
5313
+ provisionalUntil: input.finalPublication === false ? input.request : void 0,
5314
+ dev: input.devServer === true
5315
+ });
5257
5316
  const previouslyOwned = state.transformVirtualModules.get(input.owner) ?? /* @__PURE__ */ new Set();
5258
5317
  if (input.replaceOwnedArtifacts === true) {
5259
5318
  for (const staleId of previouslyOwned) {
@@ -5273,8 +5332,8 @@ function registerTransformArtifacts(state, input) {
5273
5332
  function publishesVirtualModule(next, current) {
5274
5333
  if (!current) return true;
5275
5334
  if (next.provisional === true) return false;
5335
+ if (current.provisional === true) return true;
5276
5336
  if (next.type === "resolver" && current.type === "resolver") {
5277
- if (current.provisional === true) return true;
5278
5337
  const verdict = linkedResolverClaimVerdict({
5279
5338
  resolverId: next.id,
5280
5339
  current: current.symbolClaims,
@@ -8264,7 +8323,7 @@ async function loadHook(ctx, pluginContext, id) {
8264
8323
  return executionLogVirtualModuleSource({
8265
8324
  moduleSizes: embedsDevSizes ? executionLogEstimatedSizes : void 0,
8266
8325
  attribution: embedsDevSizes ? ctx.attributionTables(moduleMetadata.symbolClaimMap().values()) : void 0,
8267
- sizesUrl: internalOptions.dev === true ? void 0 : internalOptions.publicPath?.(MARKLESS_EXECUTION_SIZES) ?? `/${MARKLESS_EXECUTION_SIZES}`
8326
+ sizesUrl: internalOptions.dev === true ? void 0 : internalOptions.publicPath?.("build/execution-sizes.json") ?? `/build/execution-sizes.json`
8268
8327
  });
8269
8328
  }
8270
8329
  const normalizedId = normalizeVirtualId$2(id);
@@ -8284,7 +8343,7 @@ async function loadHook(ctx, pluginContext, id) {
8284
8343
  }
8285
8344
  const module = await virtualModuleForRequest(ctx, normalizedId, ctx.getEnvironment(pluginContext), { waitForRegeneration: true });
8286
8345
  if (module?.provisional === true) {
8287
- const kind = module.type === "symbol" ? "SYMBOL" : "RESOLVER";
8346
+ const kind = module.type === "symbol" ? "SYMBOL" : module.type === "resolver" ? "RESOLVER" : "RENDER_DATA";
8288
8347
  throw new Error(`MARKLESS_${kind}_UNPUBLISHED: ${module.type} ${JSON.stringify(normalizedId)} was loaded before its owner ${JSON.stringify(ownerSource)} published a final compile.`);
8289
8348
  }
8290
8349
  if (module) return virtualModuleSourceForLoad(module, {
@@ -8689,12 +8748,17 @@ function registerFirstPassArtifacts(request, transformed) {
8689
8748
  environment: currentEnvironment,
8690
8749
  finalPublication: false,
8691
8750
  tracksSourceClaimPublication: false,
8751
+ devServer: internalOptions.dev === true,
8752
+ request: request.id,
8692
8753
  updateDevPrerenderHashes: internalOptions.updateDevPrerenderHashes
8693
8754
  });
8694
8755
  else {
8695
8756
  moduleMetadata.recordCaptureMetadata(source, transformed.manifest);
8696
8757
  moduleMetadata.recordSymbolClaims(manifestSource, renderDataClaimManifest(transformed.manifest, manifestSource));
8697
- moduleLinkArtifacts.set(source, moduleLinkArtifact(transformed));
8758
+ publishModuleLinkArtifact(moduleLinkArtifacts, source, moduleLinkArtifact(transformed), {
8759
+ provisionalUntil: request.id,
8760
+ dev: internalOptions.dev === true
8761
+ });
8698
8762
  }
8699
8763
  }
8700
8764
  function registerFinalTransformArtifacts(request, transformed) {
@@ -8718,6 +8782,7 @@ function registerFinalTransformArtifacts(request, transformed) {
8718
8782
  else {
8719
8783
  moduleMetadata.recordCaptureMetadata(source, transformed.manifest);
8720
8784
  moduleMetadata.recordSymbolClaims(manifestSource, renderDataClaimManifest(transformed.manifest, manifestSource));
8785
+ state.moduleLinkArtifacts(currentEnvironment).set(source, moduleLinkArtifact(transformed));
8721
8786
  }
8722
8787
  }
8723
8788
  function recordLinkedTransform(request, transformed, linkedTransformInput, linked) {
@@ -8857,7 +8922,7 @@ function sharesCanonicalRenderData(request, renderDataModule) {
8857
8922
  if (renderDataReachedFromQuery(request.id) !== void 0) return false;
8858
8923
  if (renderDataModule.type !== "render-data" || renderDataModule.canonicalRenderData !== true) return false;
8859
8924
  const registered = request.ctx.state.virtualModules.get(renderDataModule.id);
8860
- return registered?.canonicalRenderData !== true || registered.source === renderDataModule.source;
8925
+ return registered?.canonicalRenderData !== true || registered.provisional === true || registered.source === renderDataModule.source;
8861
8926
  }
8862
8927
  function registerClientRouteArtifactSource(ctx, source) {
8863
8928
  const { internalOptions } = ctx;
@@ -9020,7 +9085,10 @@ async function runFirstPassTransform(request) {
9020
9085
  } catch {
9021
9086
  throw error;
9022
9087
  }
9023
- moduleLinkArtifacts.set(source, provisional);
9088
+ publishModuleLinkArtifact(moduleLinkArtifacts, source, provisional, {
9089
+ provisionalUntil: request.id,
9090
+ dev: internalOptions.dev === true
9091
+ });
9024
9092
  const provisionalImports = await resolveImportedModuleInterfaces(pluginContext, manifestSource, provisional.moduleImports, fallbackImportedSource);
9025
9093
  let provisionalBarrels;
9026
9094
  try {
@@ -9264,4 +9332,4 @@ function pluginName(environment) {
9264
9332
  return `markless:rolldown:${environment}`;
9265
9333
  }
9266
9334
  //#endregion
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 };
9335
+ export { INLINE_DEFER_LOADER_SOURCE as A, MARKLESS_CHUNK_SPECIFIER_PREFIX as C, prefetchChunkParses as D, insertImportMapScript as E, inlineDeferSource as M, moduleIdFor as N, preflightTsrxModuleDiagnostics as O, marklessImportMapPath as S, importMapScript as T, createPreloadGraphAdder as _, collapseInitFacadeImports as a, marklessBuildManifestDir as b, collectHeadLinkInjections as c, nativePackingEnabled as d, nativePackingPlugins as f, convertManifestToBundleGraph as g, withUndemandedReExportDoors as h, marklessServer as i, createInlineDeferTriggerSource as j, transformTsrxModule 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, entryReachableModuleIds as v, MARKLESS_IMPORT_MAP_ASSET as w, marklessBuildManifestPath as x, runtimeModuleIdFromOrigin as y };
package/dist/rolldown.js CHANGED
@@ -1,3 +1,3 @@
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";
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-BLS6xeVV.js";
2
+ import { C as MARKLESS_CHUNK_SPECIFIER_PREFIX, E as insertImportMapScript, S as marklessImportMapPath, T as importMapScript, _ as createPreloadGraphAdder, b as marklessBuildManifestDir, c as collectHeadLinkInjections, g as convertManifestToBundleGraph, i as marklessServer, k as transformTsrxModule, n as marklessClient, r as marklessLib, s as createBuildMetadata, t as createMarklessRolldownPlugin, w as MARKLESS_IMPORT_MAP_ASSET, x as marklessBuildManifestPath } from "./rolldown-BMQrr9-Y.js";
3
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 };
@@ -625,8 +625,8 @@ function emitSourceModule(input) {
625
625
  const emitsSsrBody = !!input.publicSsrModuleSource && !(input.environment === "client" && (symbolsOnly || !input.prerenderRecords && !input.dev));
626
626
  const csrRootName = input.environment !== "server" && !symbolsOnly && !input.prerenderRecords && input.publicRenderRootExportName ? csrRootLocalName(input.publicRenderRootExportName) : null;
627
627
  return [
628
- !input.publicSsrModuleSource && !input.publicRenderModuleSource || symbolsOnly || !input.renderDataId || input.environment === "client" && !input.publicRenderModuleSource && !input.prerenderRecords && !input.dev && !canonicalRenderData ? "" : canonicalRenderData ? emitsSsrBody ? `import { marklessPrerenderData, marklessRenderData } from '${input.renderDataId}';` : `import { marklessPrerenderData } from '${input.renderDataId}';` : `import { marklessRenderData } from '${input.renderDataId}';`,
629
- symbolsOnly ? "" : `import { state as payloadState, view as payloadView, runtimeDemandMap as payloadRuntimeDemandMap } from '${input.payloadId}';`,
628
+ !input.publicSsrModuleSource && !input.publicRenderModuleSource || symbolsOnly || !input.renderDataId || input.environment === "client" && !input.publicRenderModuleSource && !input.prerenderRecords && !input.dev && !canonicalRenderData ? "" : canonicalRenderData ? emitsSsrBody ? `import { marklessPrerenderData, marklessRenderData } from ${singleQuoted(input.renderDataId)};` : `import { marklessPrerenderData } from ${singleQuoted(input.renderDataId)};` : `import { marklessRenderData } from ${singleQuoted(input.renderDataId)};`,
629
+ symbolsOnly ? "" : `import { state as payloadState, view as payloadView, runtimeDemandMap as payloadRuntimeDemandMap } from ${singleQuoted(input.payloadId)};`,
630
630
  input.environment === "client" && input.directCsr === true && input.hasComputedState === true ? ["import { installMarklessDerivedReconcile } from '@markless/web/fns/reconcile-plane';", "installMarklessDerivedReconcile();"].join("\n") : null,
631
631
  input.environment === "client" && input.hasComputedState === true ? emitRosterResumeLoaderInstall() : null,
632
632
  input.environment === "client" && input.hasOverlayMarks === true ? emitOverlayLoaderInstall() : null,
@@ -645,7 +645,7 @@ function emitSourceModule(input) {
645
645
  (symbolsOnly || input.publicRenderRootExportName === null) && !routeSymbols ? "export { loadSymbol };" : "",
646
646
  symbolsOnly ? "" : "export { payloadView };",
647
647
  symbolsOnly ? "" : "export { payloadRuntimeDemandMap };",
648
- input.devResumeReexport && input.environment === "client" ? `export { resumeContainerEvent } from '${resumeVirtualModuleId(input.filename)}';` : "",
648
+ input.devResumeReexport && input.environment === "client" ? `export { resumeContainerEvent } from ${singleQuoted(resumeVirtualModuleId(input.filename))};` : "",
649
649
  "",
650
650
  input.environment === "server" || symbolsOnly || input.prerenderRecords ? "" : emitPublicRenderModule(input.publicRenderModuleSource, {
651
651
  executionLogEnabled: input.executionLog !== "never",
@@ -843,9 +843,9 @@ function emitResumeModule(input) {
843
843
  ].filter((name) => resumeContainerEvent.includes(name));
844
844
  return [
845
845
  input.boundSymbolDescriptors ? `export const ${MARKLESS_BOUND_SYMBOLS_EXPORT} = ${emitBoundSymbolDescriptors(input.boundSymbolDescriptors)};` : null,
846
- input.prerenderDataId && !stagedPrerender && resumeContainerEvent.includes("marklessPrerenderData") ? `import { marklessPrerenderData } from '${input.prerenderDataId}';` : null,
847
- stagedPrerender && input.prerenderDataId ? `async function marklessLoadPrerenderData() { const module = await import('${input.lazyRenderDataId ?? input.prerenderDataId}'); return module.marklessPrerenderData; }` : null,
848
- `import { runtimeDemandMap as payloadRuntimeDemandMap } from '${input.payloadId}';`,
846
+ input.prerenderDataId && !stagedPrerender && resumeContainerEvent.includes("marklessPrerenderData") ? `import { marklessPrerenderData } from ${singleQuoted(input.prerenderDataId)};` : null,
847
+ stagedPrerender && input.prerenderDataId ? `async function marklessLoadPrerenderData() { const module = await import(${singleQuoted(input.lazyRenderDataId ?? input.prerenderDataId)}); return module.marklessPrerenderData; }` : null,
848
+ `import { runtimeDemandMap as payloadRuntimeDemandMap } from ${singleQuoted(input.payloadId)};`,
849
849
  payloadHasComputed(input.payloadState) ? [
850
850
  "import { installMarklessDerivedReconcile } from '@markless/web/fns/reconcile-plane';",
851
851
  "installMarklessDerivedReconcile();",
@@ -888,6 +888,7 @@ function emitQueuedResumeContainerEvent(source, { censusRepair = true } = {}) {
888
888
  implementation,
889
889
  "export function resumeContainerEvent(input) {",
890
890
  " const root = input.root;",
891
+ " if (input.eventIndex >= 0) input = { ...input, eventRecord: (root.__mE ||= JSON.parse(root.querySelector('script[type=\"markless/view\"]').textContent).events)[input.eventIndex] };",
891
892
  censusRepair ? " if (root.__marklessShifted) return import('@markless/web/fns/served-census-repair').then((census) => (census.marklessRepairCensus(root), resumeContainerEvent(input)));" : "",
892
893
  " if (!root.__marklessDispatch) {",
893
894
  " let handler = marklessResumeContainerEvent, tail = Promise.resolve(), done = tail, lastEvent = null, lastEventTime = undefined, seen = new WeakMap();",
@@ -1122,12 +1123,12 @@ function emitResumeContainerEvent(loadSymbolName, needsFullResume, storageFreePa
1122
1123
  "async function marklessFullResumeHandoff(handoff) {",
1123
1124
  " handoff.root.__asyncResumeRuntimeStarted = true;",
1124
1125
  ...armsOpen(" "),
1125
- ` const { resumeFromPayloadDocument } = await import('${resumeEntry}');`,
1126
+ ` const { resumeFromPayloadDocument } = await import(${singleQuoted(resumeEntry)});`,
1126
1127
  " const { runtime } = await resumeFromPayloadDocument({",
1127
1128
  " document: handoff.document,",
1128
1129
  " root: handoff.root,",
1129
1130
  ` loadSymbol: ${wakeLoadSymbol},`,
1130
- ...renderDataEntry(" ", `import('${componentRowRenderDataId}').then((data) => data.marklessPrerenderData)`),
1131
+ ...renderDataEntry(" ", `import(${singleQuoted(componentRowRenderDataId)}).then((data) => data.marklessPrerenderData)`),
1131
1132
  " });",
1132
1133
  ...armsStarted(" "),
1133
1134
  " await runtime.dispatch(handoff.event, { syncPolicyAlreadyApplied: handoff.syncPolicyAlreadyApplied === true, ignoreUnmatched: true });",
@@ -1335,7 +1336,10 @@ function emitSpecializedScalarDispatcher(actions, loadSymbolName, fallback, reso
1335
1336
  "function marklessScalarEventMatches(input, host, tagName, eventName, hostNodeId) {",
1336
1337
  " const eventTypeMatches = input.event?.type === eventName;",
1337
1338
  " if (!eventTypeMatches) return false;",
1338
- " if (!host || (tagName !== \"*\" && host.tagName.toLowerCase() !== tagName)) return false;",
1339
+ " if (!host || (tagName !== \"*\" && host.tagName.toLowerCase() !== tagName)) {",
1340
+ " if (typeof __MARKLESS_DEV_ENABLED__ === \"undefined\" || __MARKLESS_DEV_ENABLED__) void import(\"@markless/web/fns/locator-miss\").then((m) => m.marklessReportLocatorMiss(input.root, { hostNodeId, tagName }, host));",
1341
+ " return false;",
1342
+ " }",
1339
1343
  " const eventTarget = input.event?.target;",
1340
1344
  " return host === eventTarget || (!!eventTarget?.nodeType && typeof host.contains === \"function\" && host.contains(eventTarget));",
1341
1345
  "}",
@@ -1488,10 +1492,10 @@ function emitLoadSymbol(input, sourceReaderName) {
1488
1492
  if (input.symbols.length > 0 && input.symbols.length <= 8) {
1489
1493
  const direct = emitDirectSourceSymbolLoader(input.symbols, sourceReaderName);
1490
1494
  if (!input.hasBoundSymbols) return direct;
1491
- return [`const marklessSymbolResolverModule = () => import('${input.resolverId}');`, direct.replace(" return Promise.reject(new Error(`Unknown async symbol ${symbolId}`));", " return marklessSymbolResolverModule().then((mod) => mod.loadSymbol(symbolId));")].join("\n");
1495
+ return [`const marklessSymbolResolverModule = () => import(${singleQuoted(input.resolverId)});`, direct.replace(" return Promise.reject(new Error(`Unknown async symbol ${symbolId}`));", " return marklessSymbolResolverModule().then((mod) => mod.loadSymbol(symbolId));")].join("\n");
1492
1496
  }
1493
1497
  return [
1494
- `const marklessSymbolResolverModule = () => import('${input.resolverId}');`,
1498
+ `const marklessSymbolResolverModule = () => import(${singleQuoted(input.resolverId)});`,
1495
1499
  "function loadSymbol(symbolId) {",
1496
1500
  " return marklessSymbolResolverModule().then((mod) => mod.loadSymbol(symbolId));",
1497
1501
  "}"
@@ -1500,7 +1504,7 @@ function emitLoadSymbol(input, sourceReaderName) {
1500
1504
  function emitDirectSourceSymbolLoader(symbols, readerName = "readMarklessSourceSymbol") {
1501
1505
  return [
1502
1506
  "function loadSymbol(symbolId) {",
1503
- ...symbols.flatMap((symbol) => [` if (symbolId === ${JSON.stringify(symbol.id)}) return import('${symbol.lazyChunk ?? symbol.chunk}')`, ` .then((mod) => ${readerName}(mod, ${JSON.stringify(symbol.exportName)}));`]),
1507
+ ...symbols.flatMap((symbol) => [` if (symbolId === ${JSON.stringify(symbol.id)}) return import(${singleQuoted(symbol.lazyChunk ?? symbol.chunk)})`, ` .then((mod) => ${readerName}(mod, ${JSON.stringify(symbol.exportName)}));`]),
1504
1508
  " return Promise.reject(new Error(`Unknown async symbol ${symbolId}`));",
1505
1509
  "}",
1506
1510
  emitSourceSymbolExportReader(readerName)
@@ -1522,6 +1526,9 @@ function stringHash(value) {
1522
1526
  }
1523
1527
  return (hash >>> 0).toString(36);
1524
1528
  }
1529
+ function singleQuoted(value) {
1530
+ return `'${String(value).replace(/[\\']/g, "\\$&").replace(/\n/g, "\\n").replace(/\r/g, "\\r")}'`;
1531
+ }
1525
1532
  const MARKLESS_BUILD_PREFIX = `build/`;
1526
1533
  const MARKLESS_BUNDLE_GRAPH = `${MARKLESS_BUILD_PREFIX}bundle-graph.json`;
1527
1534
  const MARKLESS_EXECUTION_SIZES = `${MARKLESS_BUILD_PREFIX}execution-sizes.json`;
@@ -2211,7 +2218,7 @@ const PRERENDER_WAKE_VIRTUAL_ID_RE = /^virtual:markless:prerender-wake:([^:]+)$/
2211
2218
  const SETTLE_VIRTUAL_ID_RE = /^virtual:markless:settle:([^:]+)$/;
2212
2219
  const SYMBOL_VIRTUAL_STRING_RE = /(["'`])((?:virtual:markless:symbol:)[^"'`]+)\1/g;
2213
2220
  function stripBuildPrefix(fileName) {
2214
- return fileName.startsWith(MARKLESS_BUILD_PREFIX) ? fileName.slice(MARKLESS_BUILD_PREFIX.length) : fileName;
2221
+ return fileName.startsWith("build/") ? fileName.slice(MARKLESS_BUILD_PREFIX.length) : fileName;
2215
2222
  }
2216
2223
  function virtualModuleSourceForLoad(module, options) {
2217
2224
  if (!options.dev || module.type !== "resolver") return module.source;
package/dist/vite.js CHANGED
@@ -1,7 +1,7 @@
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";
1
+ import { a as MARKLESS_DEV_RELOADS_ATTRIBUTE, d as renderMarklessDevErrorDocument, i as MARKLESS_DEV_PAGE_EDIT_EVENT, n as MARKLESS_DEV_ERROR_CLIENT_ID, o as MARKLESS_DEV_RELOADS_EVENT, r as MARKLESS_DEV_ERROR_EVENT, t as MARKLESS_DEV_ERROR_CLEAR_EVENT, u as normalizeMarklessDevError } from "./dev-error-BEduK_R3.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-BLS6xeVV.js";
3
3
  import { n as includeOptimizedDeps, t as excludeSourceShippedDeps } from "./optimized-deps-BfzxSm6C.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";
4
+ import { A as INLINE_DEFER_LOADER_SOURCE, D as prefetchChunkParses, M as inlineDeferSource, N as moduleIdFor, O as preflightTsrxModuleDiagnostics, _ as createPreloadGraphAdder, a as collapseInitFacadeImports, d as nativePackingEnabled, f as nativePackingPlugins, h as withUndemandedReExportDoors, j 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 entryReachableModuleIds, y as runtimeModuleIdFromOrigin } from "./rolldown-BMQrr9-Y.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
7
  import { ASYNC_PROTOCOL_VERSION, PROTOCOL_CONTAINER_HOST_NODE_ID, STORAGE_SLOT_SYMBOL_KEY, escapeScriptJson, serializeRuntimeAsyncSnapshots, serializeRuntimeStateCells, storageAttributeName, storageCookieName, storageSlotEntryKeyFromGraphNodeId } from "@markless/serializer";
@@ -12,14 +12,14 @@ 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_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";
15
+ import { PROTOCOL_CONTAINER_END_COMMENT, PROTOCOL_CONTAINER_START_COMMENT, PROTOCOL_EVENT_ACTION_KIND as PROTOCOL_EVENT_ACTION_KIND$1, PROTOCOL_EVENT_HOST_ATTRIBUTE, PROTOCOL_EVENT_HOST_DELEGATED_REF, PROTOCOL_IDLE_EVENT_NAME as PROTOCOL_IDLE_EVENT_NAME$1, PROTOCOL_LOCATOR_PATHS_ATTRIBUTE, PROTOCOL_SYNC_POLICY_TABLE_TYPE, PROTOCOL_VISIBLE_EVENT_NAME, constantSyncPolicyCode, formatEventHostEntries, protocolEventDispatchesMarkless, syncPolicyNeverActs } from "@markless/serializer/protocol";
16
16
  import "@markless/serializer/resume-record-delta";
17
17
  //#region ../web/src/inline/served-census.ts
18
18
  /**
19
19
  * Pins the container's elements in DOM order as its census and returns them,
20
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
21
+ * count or the order of their tags differs from what the server measured, a
22
+ * script outside Markless changed the page first: the root is flagged for the resume module to renumber
23
23
  * the census, and no elements are returned, so nothing is matched by a shifted index.
24
24
  */
25
25
  function marklessServedCensus(root, attribute) {
@@ -30,7 +30,13 @@ function marklessServedCensus(root, attribute) {
30
30
  else if (next.data === __MARKLESS_PAGE_END__) break;
31
31
  root.__marklessCensus ||= live;
32
32
  const value = root.getAttribute?.(attribute);
33
- return value && parseInt(value) !== live.length ? (root.__marklessShifted = 1, []) : live;
33
+ const order = value?.split("|")[3];
34
+ let signature = 0;
35
+ if (order) for (const element of live.slice(1)) {
36
+ const name = element.localName ?? element.tagName ?? "";
37
+ signature = signature * 31 + name.length * 32 + (name.charCodeAt(0) | 32) | 0;
38
+ }
39
+ return value && (parseInt(value) !== live.length || order && order !== (signature >>> 0).toString(36)) ? (root.__marklessShifted = 1, []) : live;
34
40
  }
35
41
  //#endregion
36
42
  //#region ../web/src/inline/resumer.ts
@@ -328,6 +334,19 @@ function isArmBranchAnchorComment(comment) {
328
334
  * bits first: a digit from the first 32 here ends a number, one from the last 32 carries.
329
335
  */
330
336
  const PROTOCOL_LOCATOR_PATHS_DIGITS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
337
+ /** A `<template>` carrying this attribute is consumed by the parser into a shadow root: the element itself is gone too. */
338
+ const PROTOCOL_DECLARATIVE_SHADOW_ROOT_ATTRIBUTE = "shadowrootmode";
339
+ const PROTOCOL_RAW_TEXT_TAGS = /* @__PURE__ */ new Set([
340
+ "script",
341
+ "style",
342
+ "textarea",
343
+ "title",
344
+ "xmp",
345
+ "iframe",
346
+ "noembed",
347
+ "noframes",
348
+ "noscript"
349
+ ]);
331
350
  //#endregion
332
351
  //#region ../web/src/locator-paths.ts
333
352
  const VOID_TAGS = /* @__PURE__ */ new Set([
@@ -345,18 +364,8 @@ const VOID_TAGS = /* @__PURE__ */ new Set([
345
364
  "track",
346
365
  "wbr"
347
366
  ]);
348
- const RAW_TEXT_TAGS = /* @__PURE__ */ new Set([
349
- "script",
350
- "style",
351
- "textarea",
352
- "title",
353
- "xmp",
354
- "iframe",
355
- "noembed",
356
- "noframes",
357
- "noscript"
358
- ]);
359
367
  const FOREIGN_ROOTS = /* @__PURE__ */ new Set(["svg", "math"]);
368
+ const DECLARATIVE_SHADOW_ROOT = new RegExp(`\\s${PROTOCOL_DECLARATIVE_SHADOW_ROOT_ATTRIBUTE}(?:[\\s=/>]|$)`, "i");
360
369
  function servedElementTree(html) {
361
370
  const elements = [{
362
371
  tag: "",
@@ -414,7 +423,8 @@ function servedElementTree(html) {
414
423
  const selfClosing = foreignDepth > 0 && html[tagEnd - 1] === "/";
415
424
  const parent = stack.length ? stack[stack.length - 1].index : 0;
416
425
  let index = parent;
417
- if (templateDepth === 0) {
426
+ const shadowRoot = lower === "template" && DECLARATIVE_SHADOW_ROOT.test(html.slice(nameStart + name.length, tagEnd));
427
+ if (templateDepth === 0 && !shadowRoot) {
418
428
  index = elements.push({
419
429
  tag,
420
430
  parent,
@@ -424,7 +434,7 @@ function servedElementTree(html) {
424
434
  nameEnds.push(nameStart + name.length);
425
435
  }
426
436
  if (VOID_TAGS.has(lower) || selfClosing) continue;
427
- if (RAW_TEXT_TAGS.has(lower)) {
437
+ if (PROTOCOL_RAW_TEXT_TAGS.has(lower)) {
428
438
  const close = (lowerHtml ??= html.toLowerCase()).indexOf(`</${lower}`, at);
429
439
  at = close < 0 ? html.length : endOfTag(html, close + 2 + lower.length) + 1;
430
440
  continue;
@@ -443,6 +453,18 @@ function servedElementTree(html) {
443
453
  nameEnds
444
454
  };
445
455
  }
456
+ /** Writes `attribute="value"` on each element the map names by its index in servedElementTree(html). */
457
+ function withElementAttributes(html, nameEnds, attribute, values) {
458
+ let out = "";
459
+ let cursor = 0;
460
+ for (const index of [...values.keys()].sort((left, right) => left - right)) {
461
+ const at = nameEnds[index];
462
+ if (!index || at === void 0) continue;
463
+ out += `${html.slice(cursor, at)} ${attribute}="${values.get(index).replace(/&/g, "&amp;").replace(/"/g, "&quot;")}"`;
464
+ cursor = at;
465
+ }
466
+ return out + html.slice(cursor);
467
+ }
446
468
  function endOfTag(html, from) {
447
469
  let quote = "";
448
470
  for (let at = from; at < html.length; at++) {
@@ -487,7 +509,13 @@ function servedLocatorPaths(containerHtml, locators) {
487
509
  stack.push(index);
488
510
  previous = index;
489
511
  }
490
- return `${elements.length}${tags.join(",")}|${entries}|${parents.map((parent) => pathNumber(childCounts[parent])).join("")}`;
512
+ return `${elements.length}${tags.join(",")}|${entries}|${parents.map((parent) => pathNumber(childCounts[parent])).join("")}|${tagOrderSignature(elements.slice(1).map((element) => element.tag))}`;
513
+ }
514
+ /** The order the served elements' tags came in, which a script moving one changes without changing the count. */
515
+ function tagOrderSignature(tags) {
516
+ let signature = 0;
517
+ for (const tag of tags) signature = signature * 31 + tag.length * 32 + (tag.charCodeAt(0) | 32) | 0;
518
+ return (signature >>> 0).toString(36);
491
519
  }
492
520
  function pathNumber(value) {
493
521
  let digits = "";
@@ -507,15 +535,18 @@ async function assemblePrerenderPageParts(component, output, options) {
507
535
  const boot = artifactPrerenderBoot(component);
508
536
  const settle = options.armEmission && selfWake ? boot?.settle : void 0;
509
537
  const resumerScript = browserTriggers && resumeModuleUrl ? renderInlineResumerScript(settle ? renderPrerenderInlineResumerSource(settle.boot, eventNames) : boot ? renderPrerenderInlineResumerSource(selfWake ? boot.prerenderSelfWake : boot.prerender, eventNames) : createPrerenderInlineResumerSource(eventNames, resumeModuleUrl), options.nonce, resumeModuleUrl, selfWake && !settle, settle?.moduleUrl, !boot, false, deferredTriggerSource(view) + (selfWake ? "" : storageWakeSource(state, resumeModuleUrl)), artifactInlineResumerSources(component)?.defer) : "";
538
+ const head = [
539
+ renderStorageSeedScript(artifactStorageSeeds(component), options.nonce),
540
+ renderHeadInjections(artifactHeadInjections(component), options.nonce),
541
+ renderModulePreloadLinks(modulePreloads, options.nonce)
542
+ ].filter(Boolean).join("");
543
+ const policyTable = createSyncPolicyTable();
510
544
  return {
511
- head: [
512
- renderStorageSeedScript(artifactStorageSeeds(component), options.nonce),
513
- renderHeadInjections(artifactHeadInjections(component), options.nonce),
514
- renderModulePreloadLinks(modulePreloads, options.nonce)
515
- ].filter(Boolean).join(""),
545
+ head,
516
546
  container: renderContainer(options.containerId, [
517
- output.html,
547
+ resumerScript ? withEventHostMarks(view, output.html, policyTable) : output.html,
518
548
  options.armEmission,
549
+ renderSyncPolicyTableScript(policyTable.policies),
519
550
  resumerScript
520
551
  ], resumerScript ? view.locators : [])
521
552
  };
@@ -665,20 +696,95 @@ function branchServedArmEventNames(branch) {
665
696
  if (!armRecords) return [];
666
697
  return [...armRecords.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName), ...(armRecords.keyedRepeats ?? []).flatMap((repeat) => repeat.rowEvents.map((event) => event.eventName))];
667
698
  }
668
- function eventHostIndexes(view, eventName) {
669
- const hosts = new Set(view.events.filter((event) => event.eventName === eventName).map((event) => event.hostNodeId));
670
- return view.locators.filter((locator) => hosts.has(locator.hostNodeId)).map((locator) => locator.index);
699
+ const DEFERRED_EVENT_NAMES = [PROTOCOL_VISIBLE_EVENT_NAME, PROTOCOL_IDLE_EVENT_NAME$1];
700
+ /** Collects a container's conditional sync policies into its table, one row per distinct policy. */
701
+ function createSyncPolicyTable() {
702
+ const policies = [];
703
+ const rows = /* @__PURE__ */ new Map();
704
+ return {
705
+ policies,
706
+ entry(policy) {
707
+ if (!policy || syncPolicyNeverActs(policy)) return void 0;
708
+ const constant = constantSyncPolicyCode(policy);
709
+ if (constant) return constant;
710
+ const key = JSON.stringify(policy);
711
+ let row = rows.get(key);
712
+ if (row === void 0) rows.set(key, row = policies.push(policy) - 1);
713
+ return row;
714
+ }
715
+ };
716
+ }
717
+ function addEventHostEntry(marks, index, entry) {
718
+ const entries = marks.get(index);
719
+ if (!entries) return void marks.set(index, [entry]);
720
+ const same = entries.findIndex((candidate) => candidate.name === entry.name);
721
+ if (same < 0) entries.push(entry);
722
+ else if (entries[same].ref === void 0 && entry.ref !== void 0) entries[same] = entry;
723
+ }
724
+ function writeEventHostMarks(html, nameEnds, marks) {
725
+ return marks.size ? withElementAttributes(html, nameEnds, PROTOCOL_EVENT_HOST_ATTRIBUTE, new Map([...marks].map(([index, entries]) => [index, formatEventHostEntries(entries)]))) : html;
726
+ }
727
+ /**
728
+ * Writes the `m:on` attribute on every served event host: a top-level record by
729
+ * its index in `events`, a keyed repeat parent as the scope of its rows' events,
730
+ * and a host in a served arm by the policy its record carries.
731
+ */
732
+ function withEventHostMarks(view, html, policyTable) {
733
+ const tree = servedElementTree(html);
734
+ const marks = /* @__PURE__ */ new Map();
735
+ const indexes = (locators) => new Map(locators.map((locator) => [locator.hostNodeId, locator.index]));
736
+ const shell = indexes(view.locators);
737
+ view.events.forEach((event, ref) => {
738
+ const index = shell.get(event.hostNodeId);
739
+ if (index === void 0) return;
740
+ const dispatches = protocolEventDispatchesMarkless(event);
741
+ if (!dispatches && DEFERRED_EVENT_NAMES.includes(event.eventName)) return;
742
+ const policy = policyTable.entry(event.syncPolicy);
743
+ addEventHostEntry(marks, index, {
744
+ name: event.eventName,
745
+ ref: dispatches ? ref : PROTOCOL_EVENT_HOST_DELEGATED_REF,
746
+ ...policy === void 0 ? {} : { policy }
747
+ });
748
+ });
749
+ for (const repeat of view.keyedRepeats ?? []) {
750
+ const index = shell.get(repeat.parentHostNodeId);
751
+ if (index === void 0) continue;
752
+ for (const event of repeat.rowEvents) addEventHostEntry(marks, index, { name: event.eventName });
753
+ }
754
+ for (const [anchor, records] of [...view.asyncBoundaries.map((boundary) => [boundary.startAnchor, boundary.armRecords]), ...(view.branches ?? []).map((branch) => [branch.startAnchor, branch.servedArmRecords])]) {
755
+ if (!records || Array.isArray(records)) continue;
756
+ const set = records;
757
+ const offset = tree.commentElementIndexes[anchor.index];
758
+ if (offset === void 0) continue;
759
+ const arm = indexes(set.locators);
760
+ for (const event of set.events ?? []) {
761
+ const policy = policyTable.entry(event.syncPolicy);
762
+ const index = arm.get(event.hostNodeId);
763
+ if (policy === void 0 || index === void 0) continue;
764
+ addEventHostEntry(marks, offset + index, {
765
+ name: event.eventName,
766
+ policy
767
+ });
768
+ }
769
+ }
770
+ return writeEventHostMarks(html, tree.nameEnds, marks);
771
+ }
772
+ function renderSyncPolicyTableScript(policies) {
773
+ return policies.length ? `<script type="${PROTOCOL_SYNC_POLICY_TABLE_TYPE}">${escapeScriptJson(JSON.stringify(policies))}<\/script>` : "";
774
+ }
775
+ function hasEvent(view, eventName) {
776
+ return view.events.some((event) => event.eventName === eventName);
671
777
  }
672
778
  function deferredTriggerSource(view) {
673
- const visible = eventHostIndexes(view, PROTOCOL_VISIBLE_EVENT_NAME);
674
- const idle = eventHostIndexes(view, PROTOCOL_IDLE_EVENT_NAME$1);
675
779
  const nested = deferredEventNames({
676
780
  ...view,
677
781
  events: []
678
782
  });
679
- if (nested.includes(PROTOCOL_VISIBLE_EVENT_NAME)) visible.push(0);
680
- if (nested.includes(PROTOCOL_IDLE_EVENT_NAME$1)) idle.push(0);
681
- return (visible.length > 0 ? createInlineDeferTriggerSource("visible", visible) : "") + (idle.length > 0 ? createInlineDeferTriggerSource("idle", idle) : "");
783
+ const lane = (name, eventName) => {
784
+ const ownsRoot = nested.includes(eventName);
785
+ return hasEvent(view, eventName) || ownsRoot ? createInlineDeferTriggerSource(name, ownsRoot) : "";
786
+ };
787
+ return lane("visible", PROTOCOL_VISIBLE_EVENT_NAME) + lane("idle", PROTOCOL_IDLE_EVENT_NAME$1);
682
788
  }
683
789
  function browserEventNames(view) {
684
790
  return deferredEventNames(view).filter((eventName) => eventName !== PROTOCOL_VISIBLE_EVENT_NAME);
@@ -1284,7 +1390,7 @@ function deferredRuntimePlugin(demandMaps) {
1284
1390
  packs = /* @__PURE__ */ new Map();
1285
1391
  if (error) return;
1286
1392
  const modules = /* @__PURE__ */ new Map();
1287
- for (const id of this.getModuleIds()) {
1393
+ for (const id of entryReachableModuleIds(this)) {
1288
1394
  const info = this.getModuleInfo(id);
1289
1395
  if (!info || "isExternal" in info && info.isExternal) continue;
1290
1396
  modules.set(id, {
@@ -1354,6 +1460,7 @@ const ERROR_EVENT = ${JSON.stringify(MARKLESS_DEV_ERROR_EVENT)};
1354
1460
  const CLEAR_EVENT = ${JSON.stringify(MARKLESS_DEV_ERROR_CLEAR_EVENT)};
1355
1461
  const RELOADS_EVENT = ${JSON.stringify(MARKLESS_DEV_RELOADS_EVENT)};
1356
1462
  const RELOADS_ATTRIBUTE = ${JSON.stringify(MARKLESS_DEV_RELOADS_ATTRIBUTE)};
1463
+ const PAGE_EDIT_EVENT = ${JSON.stringify(MARKLESS_DEV_PAGE_EDIT_EVENT)};
1357
1464
  const ELEMENT = 'markless-dev-error-overlay';
1358
1465
  const SUPPRESSION = 'data-markless-vite-overlay-suppression';
1359
1466
  const OPEN_IN_EDITOR = ${JSON.stringify(`${base}/__open-in-editor`)};
@@ -1428,7 +1535,9 @@ hot.on('vite:beforeFullReload', reset);
1428
1535
  addEventListener('keydown', (event) => { if (event.key === 'Escape') document.querySelector(ELEMENT)?.remove(); });
1429
1536
  if (window.__MARKLESS_DEV_ERROR__) show(window.__MARKLESS_DEV_ERROR__);
1430
1537
  const servedAfter = document.querySelector('script[' + RELOADS_ATTRIBUTE + ']')?.getAttribute(RELOADS_ATTRIBUTE);
1431
- if (servedAfter != null) hot.send(RELOADS_EVENT, { reloads: Number(servedAfter) });
1538
+ const report = (edit) => hot.send(RELOADS_EVENT, { reloads: servedAfter != null ? Number(servedAfter) : edit, href: location.href });
1539
+ if (servedAfter != null) report();
1540
+ hot.on(PAGE_EDIT_EVENT, ({ edit }) => report(edit));
1432
1541
  `;
1433
1542
  }
1434
1543
  //#endregion
@@ -1493,12 +1602,19 @@ function createViteHmr(options) {
1493
1602
  let recheckingInvalidSources = false;
1494
1603
  const preflightByFile = /* @__PURE__ */ new Map();
1495
1604
  const unreportedInvalidations = /* @__PURE__ */ new Map();
1496
- let editReloads = 0;
1605
+ const edits = [];
1497
1606
  let lastReloadedEdit;
1498
- function countEditReload(edit) {
1499
- if (edit === lastReloadedEdit) return;
1607
+ function recordEdit(edit, pages) {
1608
+ if (edit === lastReloadedEdit) return void 0;
1500
1609
  lastReloadedEdit = edit;
1501
- editReloads += 1;
1610
+ return edits.push(pages) - 1;
1611
+ }
1612
+ function servedPageIsStale(data) {
1613
+ const since = typeof data?.reloads === "number" ? data.reloads : edits.length;
1614
+ const later = edits.slice(Math.max(0, since));
1615
+ if (later.length === 0) return false;
1616
+ const page = typeof data?.href === "string" && options.pageForUrl ? options.pageForUrl(data.href) : void 0;
1617
+ return later.some((pages) => pages === "all" || page === void 0 || pages.has(page));
1502
1618
  }
1503
1619
  let hotUpdatePasses = 0;
1504
1620
  let hotUpdateCycle;
@@ -1624,7 +1740,7 @@ function createViteHmr(options) {
1624
1740
  recovered = true;
1625
1741
  }
1626
1742
  if (recovered) {
1627
- countEditReload(`recovered\0${Date.now()}`);
1743
+ recordEdit(`recovered\0${Date.now()}`, "all");
1628
1744
  server?.environments?.[options.clientEnvironment]?.hot?.send?.({ type: "full-reload" });
1629
1745
  }
1630
1746
  } finally {
@@ -1654,10 +1770,10 @@ function createViteHmr(options) {
1654
1770
  if (options.enabled) {
1655
1771
  installFetchViteClient(nextServer, options, async () => {
1656
1772
  await settledHotUpdate();
1657
- return editReloads;
1773
+ return edits.length;
1658
1774
  });
1659
1775
  nextServer.environments?.[options.clientEnvironment]?.hot?.on?.(MARKLESS_DEV_RELOADS_EVENT, (data, client) => {
1660
- if (data?.reloads !== editReloads) client.send({ type: "full-reload" });
1776
+ if (servedPageIsStale(data)) client.send({ type: "full-reload" });
1661
1777
  });
1662
1778
  }
1663
1779
  },
@@ -1699,6 +1815,38 @@ function createViteHmr(options) {
1699
1815
  }
1700
1816
  return !answered;
1701
1817
  }
1818
+ function editedPages(targets, file) {
1819
+ const isPage = options.isPage;
1820
+ const root = server?.config?.root;
1821
+ if (!isPage || !options.pageForUrl || !root) return "all";
1822
+ const pageOf = (module) => {
1823
+ const id = module.file ? moduleIdFor(module.file, root) : void 0;
1824
+ return id !== void 0 && isPage(id) ? id : void 0;
1825
+ };
1826
+ const pending = [];
1827
+ for (const [target, scope] of targets) {
1828
+ if (scope !== "server") continue;
1829
+ pending.push(...target.moduleGraph?.getModulesByFile?.(parsePath(file).pathname) ?? []);
1830
+ }
1831
+ if (pending.length === 0) return "all";
1832
+ const pages = /* @__PURE__ */ new Set();
1833
+ const seen = /* @__PURE__ */ new Set();
1834
+ while (pending.length > 0) {
1835
+ const module = pending.pop();
1836
+ if (seen.has(module)) continue;
1837
+ seen.add(module);
1838
+ const page = pageOf(module);
1839
+ const importers = [...module.importers ?? []];
1840
+ if (page) {
1841
+ pages.add(page);
1842
+ pending.push(...importers.filter((importer) => pageOf(importer)));
1843
+ continue;
1844
+ }
1845
+ if (importers.length === 0) return "all";
1846
+ pending.push(...importers);
1847
+ }
1848
+ return pages;
1849
+ }
1702
1850
  async function runHotUpdate(environment, ctx) {
1703
1851
  if (!environment) return;
1704
1852
  const env = marklessEnvironment(environment);
@@ -1717,7 +1865,22 @@ function createViteHmr(options) {
1717
1865
  }
1718
1866
  const modules = new Set(ctx.modules ?? []);
1719
1867
  if (ctx.file) for (const target of targets.keys()) for (const module of target.moduleGraph?.getModulesByFile?.(ctx.file) ?? []) modules.add(module);
1868
+ const listingModules = /* @__PURE__ */ new Map();
1869
+ if (ctx.type !== "update") {
1870
+ listingModules.set(environment, new Set(ctx.modules ?? []));
1871
+ for (const target of targets.keys()) for (const module of await globImporters(target, ctx)) {
1872
+ const listed = listingModules.get(target) ?? /* @__PURE__ */ new Set();
1873
+ listed.add(module);
1874
+ listingModules.set(target, listed);
1875
+ modules.add(module);
1876
+ }
1877
+ }
1720
1878
  if (modules.size === 0 && ctx.file && !loadedOrInvalid(targets.keys(), ctx.file)) return [];
1879
+ for (const [target, listed] of listingModules) for (const module of listed) {
1880
+ const invalidated = /* @__PURE__ */ new Set();
1881
+ target.moduleGraph?.invalidateModule?.(module, invalidated, ctx.timestamp, true);
1882
+ recordUnreportedInvalidation(target, invalidated);
1883
+ }
1721
1884
  const files = changedFiles([...modules]);
1722
1885
  const root = server?.config?.root;
1723
1886
  if (ctx.file && SOURCE_FILE_EXTENSION.test(ctx.file)) {
@@ -1781,15 +1944,31 @@ function createViteHmr(options) {
1781
1944
  recordUnreportedInvalidation(targetEnvironment, invalidated);
1782
1945
  }
1783
1946
  reloadModuleRunner();
1784
- countEditReload(`${ctx.file}\0${ctx.timestamp}`);
1785
- hot.send({
1947
+ const pages = ctx.type === "update" && ctx.file ? editedPages(targets, ctx.file) : "all";
1948
+ const edit = recordEdit(`${ctx.file}\0${ctx.timestamp}`, pages);
1949
+ if (pages === "all") hot.send({
1786
1950
  type: "full-reload",
1787
1951
  path: firstChangedFile(files),
1788
1952
  triggeredBy: ctx.file
1789
1953
  });
1954
+ else if (edit !== void 0) hot.send({
1955
+ type: "custom",
1956
+ event: MARKLESS_DEV_PAGE_EDIT_EVENT,
1957
+ data: { edit }
1958
+ });
1790
1959
  return [];
1791
1960
  }
1792
1961
  }
1962
+ async function globImporters(environment, ctx) {
1963
+ const hook = (environment.plugins?.find((candidate) => candidate.name === "vite:import-glob"))?.hotUpdate;
1964
+ const handler = typeof hook === "function" ? hook : hook?.handler;
1965
+ if (!handler) return [];
1966
+ const modules = await handler.call({ environment }, {
1967
+ ...ctx,
1968
+ modules: []
1969
+ });
1970
+ return Array.isArray(modules) ? modules : [];
1971
+ }
1793
1972
  async function fetchedModuleNode(environment, id) {
1794
1973
  const resolved = id.startsWith(VITE_ID_PREFIX) ? id.slice(5).replace(VITE_NULL_BYTE, "\0") : id;
1795
1974
  return environment.moduleGraph.getModuleById(resolved) ?? await environment.moduleGraph.getModuleByUrl(id).catch(() => void 0);
@@ -2018,7 +2197,9 @@ function markless(options = {}) {
2018
2197
  clientEnvironment: viteEnvironmentName("client", options),
2019
2198
  enabled: false,
2020
2199
  invalidateGeneratedModules: (parent, environment, nextSource) => marklessPlugin.api.invalidateGeneratedModules(parent, environment, nextSource),
2021
- invalidatePrerenderSnapshots: void 0
2200
+ invalidatePrerenderSnapshots: void 0,
2201
+ isPage: void 0,
2202
+ pageForUrl: void 0
2022
2203
  };
2023
2204
  let devPrerender;
2024
2205
  const devTags = createDevTags();
@@ -2036,6 +2217,13 @@ function markless(options = {}) {
2036
2217
  sharedDuringBuild: true,
2037
2218
  api: {
2038
2219
  ...basePlugin.api,
2220
+ declareRouteModules: (isRoute) => {
2221
+ basePlugin.api.declareRouteModules(isRoute);
2222
+ hmrOptions.isPage = isRoute;
2223
+ },
2224
+ declarePageForUrl: (pageForUrl) => {
2225
+ hmrOptions.pageForUrl = pageForUrl;
2226
+ },
2039
2227
  registerBundleGraphAdder: (adder) => bundleGraphAdders.add(adder),
2040
2228
  registerDevInjection: (injection) => devTags.register(injection),
2041
2229
  registerPreloadGraphEntries: (adder) => bundleGraphAdders.add(createPreloadGraphAdder(adder))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markless/bundler",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "Markless build plugins for Rolldown and Vite.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -36,19 +36,19 @@
36
36
  "provenance": true
37
37
  },
38
38
  "dependencies": {
39
- "@thi.ng/dgraph": "^2.1.205",
39
+ "@thi.ng/dgraph": "^2.1.213",
40
40
  "pathe": "^2.0.3",
41
41
  "ufo": "^1.6.4",
42
- "@markless/compiler": "0.6.0",
43
- "@markless/serializer": "0.6.0",
44
- "@markless/web": "0.6.0"
42
+ "@markless/compiler": "0.8.0",
43
+ "@markless/web": "0.8.0",
44
+ "@markless/serializer": "0.8.0"
45
45
  },
46
46
  "devDependencies": {
47
- "@markless/analyzer": "0.6.0"
47
+ "@markless/analyzer": "0.8.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "rolldown": "1.2.7",
51
- "vite": "8.2.2"
50
+ "rolldown": "1.2.14",
51
+ "vite": "8.3.4"
52
52
  },
53
53
  "peerDependenciesMeta": {
54
54
  "rolldown": {