@markless/bundler 0.3.3 → 0.5.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.
package/dist/vite.js CHANGED
@@ -1,28 +1,67 @@
1
- import { MARKLESS_DEV_ERROR_CLEAR_EVENT, MARKLESS_DEV_ERROR_CLIENT_ID, MARKLESS_DEV_ERROR_EVENT, normalizeMarklessDevError, renderMarklessDevErrorDocument } from "./dev-error.js";
2
- import { _ as executionLogActivationInjection } from "./source-module-CZFm1uWH.js";
3
- import { d as outputDefaults, o as preflightTsrxModuleDiagnostics, p as createPreloadGraphAdder, t as createMarklessRolldownPlugin } from "./rolldown-FRjFod14.js";
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";
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";
5
+ import { n as marklessRosterPositions, r as marklessRosterRenderContext, t as marklessRosterPositionSeeds } from "./shared-seed-slot-ihIVCD2S.js";
4
6
  import { joinURL, parsePath, withQuery } from "ufo";
5
- import { ASYNC_PROTOCOL_VERSION, STORAGE_SLOT_SYMBOL_KEY, serializeRuntimeAsyncSnapshots, serializeRuntimeStateCells, storageAttributeName } from "@markless/serializer";
6
- import { pathToFileURL } from "node:url";
7
- import { join, resolve } from "pathe";
7
+ import { ASYNC_PROTOCOL_VERSION, STORAGE_SLOT_SYMBOL_KEY, escapeScriptJson, serializeRuntimeAsyncSnapshots, serializeRuntimeStateCells, storageAttributeName, storageCookieName, storageSlotEntryKeyFromGraphNodeId } from "@markless/serializer";
8
+ import { isAbsolute, join, resolve } from "pathe";
9
+ import { DEBUGGING_PLAYBOOK_HINT } from "@markless/compiler";
8
10
  import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
11
+ import { isAbsolute as isAbsolute$1 } from "node:path";
12
+ import { pathToFileURL } from "node:url";
13
+ import { createServerModuleRunner, isRunnableDevEnvironment } from "vite";
9
14
  import { tmpdir } from "node:os";
10
- import { PROTOCOL_EVENT_ACTION_KIND as PROTOCOL_EVENT_ACTION_KIND$1, protocolEventDispatchesMarkless } from "@markless/serializer/protocol";
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";
11
16
  import "@markless/serializer/resume-record-delta";
12
- import { deserializeGraphValueForClient } from "@markless/serializer/decode-client";
13
- import { createServerModuleRunner, isRunnableDevEnvironment } from "vite";
14
- import { isAbsolute as isAbsolute$1 } from "node:path";
17
+ //#region ../web/src/inline/served-census.ts
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.
24
+ */
25
+ function marklessServedCensus(root, attribute) {
26
+ const live = [root];
27
+ const walker = document.createTreeWalker(root, 1);
28
+ for (let next = walker.nextNode(); next; next = walker.nextNode()) live.push(next);
29
+ root.__marklessCensus ||= live;
30
+ const value = root.getAttribute?.(attribute);
31
+ return value && parseInt(value) !== live.length ? (root.__marklessShifted = 1, []) : live;
32
+ }
33
+ //#endregion
15
34
  //#region ../web/src/inline/resumer.ts
16
35
  PROTOCOL_EVENT_ACTION_KIND$1.event, PROTOCOL_EVENT_ACTION_KIND$1.externalDelegate;
36
+ const INLINE_MODULE_LOADER_SOURCE = INLINE_DEFER_LOADER_SOURCE;
17
37
  function createInlineResumerSelfWakeSource(resumeModuleUrl) {
18
- return `;(${runInlineResumerSelfWake.toString()})(${JSON.stringify(resumeModuleUrl)});`;
38
+ return `;(${runInlineResumerSelfWake.toString()})(${JSON.stringify(resumeModuleUrl)},${INLINE_MODULE_LOADER_SOURCE},${inlineDeferSource()});`;
39
+ }
40
+ function createInlineResumerStorageWakeSource(resumeModuleUrl, slotSymbolKey, renderedJson) {
41
+ return `;(${runInlineResumerStorageWake.toString()})(${JSON.stringify(slotSymbolKey)},${renderedJson},()=>(${runInlineResumerSelfWake.toString()})(${JSON.stringify(resumeModuleUrl)},${INLINE_MODULE_LOADER_SOURCE},${inlineDeferSource()}));`;
42
+ }
43
+ function runInlineResumerStorageWake(slotSymbolKey, rendered, wake) {
44
+ const slot = globalThis[Symbol.for(slotSymbolKey)];
45
+ if (slot && rendered.some(([key, value]) => Object.hasOwn(slot, key) && slot[key] !== value)) wake();
46
+ }
47
+ /**
48
+ * The Escape primer, appended only to a page whose served HTML carries an
49
+ * `overlay` mark.
50
+ *
51
+ * Appended rather than composed into the resumer body for the same reason the
52
+ * self-wake is: the body is serialized whole, so a flag inside it would put the
53
+ * text on every page in the world to serve the few that elevate anything. A page
54
+ * with no mark ships a byte-identical resumer.
55
+ */
56
+ function createInlineResumerOverlayPrimerSource(resumeModuleUrl) {
57
+ return `;(${runInlineResumerOverlayPrimer.toString()})(${JSON.stringify(resumeModuleUrl)},${INLINE_MODULE_LOADER_SOURCE});`;
19
58
  }
20
59
  const PRERENDER_INLINE_EVENT_NAMES_TOKEN = "__MARKLESS_PRERENDER_EVENT_NAMES__";
21
60
  function renderPrerenderInlineResumerSource(compiled, eventNames) {
22
61
  return compiled.replace(PRERENDER_INLINE_EVENT_NAMES_TOKEN, JSON.stringify(eventNames));
23
62
  }
24
63
  function createPrerenderInlineResumerSource(eventNames, resumeModuleUrl, options) {
25
- const plain = `(${runPrerenderInlineResumer.toString()})(${JSON.stringify(eventNames)},${JSON.stringify(resumeModuleUrl)},u=>import(u));`;
64
+ const plain = `(${runPrerenderInlineResumer.toString()})(${JSON.stringify(eventNames)},${JSON.stringify(resumeModuleUrl)},u=>import(u),${marklessServedCensus.toString()},${JSON.stringify(PROTOCOL_LOCATOR_PATHS_ATTRIBUTE)});`;
26
65
  const logging = options?.executionLog !== void 0 && options.executionLog !== "never";
27
66
  if (!options?.debug && !logging) return plain;
28
67
  return `{
@@ -109,111 +148,69 @@ function runPrerenderInlineResumerDebugSetup(eventNames) {
109
148
  controls?.activate();
110
149
  } catch {}
111
150
  }
112
- function runPrerenderInlineResumer(eventNames, fallbackResumeModuleUrl, loadModule) {
151
+ function runPrerenderInlineResumer(eventNames, fallbackResumeModuleUrl, loadModule, census, pathsAttribute) {
113
152
  const currentScript = document.currentScript;
114
153
  const root = currentScript?.closest("[data-async-container]");
115
154
  const resumeModuleUrl = currentScript?.getAttribute?.("data-markless-resume-module") ?? fallbackResumeModuleUrl;
116
155
  if (!root || !resumeModuleUrl) return;
117
- for (const eventName of eventNames) root.addEventListener(eventName, (event) => {
156
+ let loaded;
157
+ const dispatch = (event) => {
118
158
  root.__marklessDelegatedDispatch = true;
119
- return loadModule(resumeModuleUrl).then((module) => module.resumeContainerEvent({
159
+ if (!root.__marklessCensus) census(root, pathsAttribute);
160
+ return (loaded ||= loadModule(resumeModuleUrl)).then((module) => module.resumeContainerEvent({
120
161
  root,
121
162
  event,
122
163
  element: event.target,
123
164
  eventRecord: null
124
165
  }));
125
- }, true);
166
+ };
167
+ eventNames.map(root.__marklessListen = (eventName) => root.addEventListener(eventName, dispatch, true));
126
168
  }
127
- function runInlineResumerSelfWake(fallbackResumeModuleUrl) {
169
+ function runInlineResumerSelfWake(fallbackResumeModuleUrl, loadModule, defer) {
128
170
  const currentScript = document.currentScript;
129
171
  const root = currentScript?.closest("[data-async-container]");
130
172
  const resumeModuleUrl = currentScript?.getAttribute?.("data-markless-resume-module") ?? fallbackResumeModuleUrl;
131
173
  if (!root || !resumeModuleUrl) return;
132
- const wake = () => requestAnimationFrame(() => {
133
- queueMicrotask(async () => {
134
- if (!root.__asyncResumeRuntimeStarted) {
135
- root.__marklessDelegatedDispatch = true;
136
- await (await import(
137
- /* @vite-ignore */
138
- resumeModuleUrl
139
- )).resumeContainerEvent({
140
- root,
141
- event: 0
142
- });
143
- }
174
+ defer.idle(root, async () => {
175
+ if (root.__asyncResumeRuntimeStarted) return;
176
+ root.__marklessDelegatedDispatch = true;
177
+ await (await loadModule(resumeModuleUrl)).resumeContainerEvent({
178
+ root,
179
+ event: 0
144
180
  });
145
181
  });
146
- if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", wake, { once: true });
147
- else wake();
148
182
  }
149
- //#endregion
150
- //#region ../web/src/repeat-runtime.ts
151
- var KeyedRepeatRuntimeError = class extends Error {
152
- code = "MARKLESS_REPEAT_KEY_DUPLICATE";
153
- severity = "error";
154
- phase = "runtime";
155
- repeatId;
156
- keyPath;
157
- collidingValue;
158
- docsUrl;
159
- constructor(diagnostic) {
160
- super(diagnostic.message);
161
- Object.defineProperty(this, "message", {
162
- value: diagnostic.message,
163
- enumerable: true,
164
- configurable: true
183
+ function runInlineResumerOverlayPrimer(fallbackResumeModuleUrl, loadModule) {
184
+ const currentScript = document.currentScript;
185
+ const root = currentScript?.closest("[data-async-container]");
186
+ const resumeModuleUrl = currentScript?.getAttribute?.("data-markless-resume-module") ?? fallbackResumeModuleUrl;
187
+ if (!root || !resumeModuleUrl) return;
188
+ const prime = (event) => {
189
+ if (root.__marklessOverlayInstalled) {
190
+ removeEventListener("keydown", prime, true);
191
+ removeEventListener("pointerdown", prime, true);
192
+ return;
193
+ }
194
+ if (!root.querySelector("[overlay]:not([hidden])")) return;
195
+ if (event.key === "Escape") root.__marklessOverlayPrimedDismissal = "escape";
196
+ if (root.__marklessDelegatedDispatch === true) return;
197
+ if (!root.__marklessCensus) {
198
+ const census = [root];
199
+ const all = root.getElementsByTagName?.("*") ?? [];
200
+ for (let index = 0; index < all.length; index++) census.push(all[index]);
201
+ root.__marklessCensus = census;
202
+ }
203
+ setTimeout(() => {
204
+ if (root.__marklessDelegatedDispatch === true) return;
205
+ root.__marklessDelegatedDispatch = true;
206
+ loadModule(resumeModuleUrl).then((module) => module.resumeContainerEvent({
207
+ root,
208
+ event: 0
209
+ }));
165
210
  });
166
- this.name = "KeyedRepeatRuntimeError";
167
- this.repeatId = diagnostic.repeatId;
168
- this.keyPath = diagnostic.keyPath;
169
- this.collidingValue = diagnostic.collidingValue;
170
- this.docsUrl = diagnostic.docsUrl;
171
- }
172
- };
173
- function validateKeyedRepeatGraphKeys(graph, view) {
174
- for (const repeat of view.keyedRepeats ?? []) assertUniqueRepeatKeys(repeat, readKeyedRepeatCollection(graph, repeat));
175
- }
176
- async function validateKeyedRepeatPayloadKeys(input) {
177
- const entries = await Promise.all(input.state.cells.map(async (cell) => [cell.graphNodeId, cell.value === void 0 ? void 0 : await deserializeGraphValueForClient(cell.value)]));
178
- const cells = new Map(entries);
179
- validateKeyedRepeatGraphKeys({ read(graphNodeId, path = []) {
180
- return readPath(cells.get(graphNodeId), path);
181
- } }, input.view);
182
- }
183
- function readKeyedRepeatCollection(graph, repeat) {
184
- if (!repeat.collectionGraphNodeId) return [];
185
- const value = graph.read(repeat.collectionGraphNodeId, repeat.collectionPath);
186
- if (Array.isArray(value)) return value;
187
- return Array.from(value ?? []);
188
- }
189
- function repeatItemKey(item, repeat) {
190
- return readPath(item, repeat.keyPath);
191
- }
192
- function assertUniqueRepeatKeys(repeat, items) {
193
- const seen = /* @__PURE__ */ new Map();
194
- for (const item of items) {
195
- const key = repeatItemKey(item, repeat);
196
- if (seen.has(key)) throw duplicateRepeatKeyError(repeat, key);
197
- seen.set(key, true);
198
- }
199
- }
200
- function duplicateRepeatKeyError(repeat, key) {
201
- const source = `${repeat.itemName}.${repeat.keyPath.join(".")}`;
202
- return new KeyedRepeatRuntimeError({
203
- message: `MARKLESS_REPEAT_KEY_DUPLICATE: Duplicate @for key ${JSON.stringify(key)} from ${source}.`,
204
- repeatId: repeat.id,
205
- keyPath: repeat.keyPath,
206
- collidingValue: key,
207
- docsUrl: "https://markless.dev/errors/MARKLESS_REPEAT_KEY_DUPLICATE"
208
- });
209
- }
210
- function readPath(value, path) {
211
- let cursor = value;
212
- for (const key of path) {
213
- if (cursor == null) return void 0;
214
- cursor = cursor[key];
215
- }
216
- return cursor;
211
+ };
212
+ addEventListener("keydown", prime, true);
213
+ addEventListener("pointerdown", prime, true);
217
214
  }
218
215
  //#endregion
219
216
  //#region ../web/src/prerender/records.ts
@@ -225,7 +222,7 @@ async function prepareSsrResumeRecords(output) {
225
222
  computed: serializeRuntimeAsyncSnapshots(rawState.computed ?? [])
226
223
  };
227
224
  const view = containerScopedView(output.view ?? emptyViewPayload());
228
- await validateKeyedRepeatPayloadKeys({
225
+ if (view.keyedRepeats?.length) await (await import("./repeat-runtime-BDnaUYXM.js")).validateKeyedRepeatPayloadKeys({
229
226
  state,
230
227
  view
231
228
  });
@@ -262,6 +259,34 @@ function emptyViewPayload() {
262
259
  };
263
260
  }
264
261
  //#endregion
262
+ //#region ../web/src/fns/roster-position.ts
263
+ /**
264
+ * The server render context with the roster channels on it. One counter per
265
+ * render, held by the closure rather than by a module, so two page renders in
266
+ * one process never share a count.
267
+ */
268
+ function marklessSsrRosterPositionContext(renderContext) {
269
+ const context = renderContext ?? {};
270
+ if (typeof context.rosterPosition === "function") return renderContext;
271
+ const sharedSeeds = marklessRosterPositionSeeds(context.sharedSeeds);
272
+ return {
273
+ ...context,
274
+ sharedSeeds,
275
+ ...marklessRosterRenderContext(marklessRosterPositions(sharedSeeds), void 0)
276
+ };
277
+ }
278
+ /**
279
+ * The counts this render minted, answered from the page it produced. A count is
280
+ * asked before the members it counts have rendered, so this is where it becomes
281
+ * a number — after composition, off the served view's own roster.
282
+ */
283
+ async function marklessSsrRosterCounted(renderContext, surface) {
284
+ if (!marklessRosterPositions((renderContext ?? {}).sharedSeeds)?.counted) return surface;
285
+ const roster = await globalThis.__marklessRosterResume?.();
286
+ if (!roster) throw new Error("MARKLESS_ROSTER_COUNT_UNRESOLVED");
287
+ return roster.marklessResolveRosterCounts(surface);
288
+ }
289
+ //#endregion
265
290
  //#region ../web/src/prerender/evaluator.ts
266
291
  async function evaluateBuiltPageClosure(page, props) {
267
292
  const renderContext = { prerender: true };
@@ -270,7 +295,192 @@ async function evaluateBuiltPageClosure(page, props) {
270
295
  throw new TypeError("Prerender resume requires a compiled TSRX artifact.");
271
296
  }
272
297
  //#endregion
298
+ //#region ../web/src/resume-anchor-census.ts
299
+ function isArmBranchAnchorComment(comment) {
300
+ const text = comment.data ?? comment.textContent ?? "";
301
+ return text.startsWith("markless:arm-branch:") || text.startsWith("/markless:arm-branch:");
302
+ }
303
+ //#endregion
304
+ //#region ../serializer/src/protocol-locator-paths-format.ts
305
+ /**
306
+ * The value of PROTOCOL_LOCATOR_PATHS_ATTRIBUTE: the served element count in decimal, the tag
307
+ * table joined by `,`, `|`, then for every located element and each of its ancestors, in tree
308
+ * order, four numbers: how many levels to step up from the previous entry to reach its parent (the
309
+ * container is 0), its DOM-order index as a delta from the previous entry, its place among the
310
+ * parent's element children, and its tag's place in the table; then `|` and each parent's served
311
+ * element-child count, in the order entries first name that parent. Numbers are written low five
312
+ * bits first: a digit from the first 32 here ends a number, one from the last 32 carries.
313
+ */
314
+ const PROTOCOL_LOCATOR_PATHS_DIGITS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
315
+ //#endregion
316
+ //#region ../web/src/locator-paths.ts
317
+ const VOID_TAGS = /* @__PURE__ */ new Set([
318
+ "area",
319
+ "base",
320
+ "br",
321
+ "col",
322
+ "embed",
323
+ "hr",
324
+ "img",
325
+ "input",
326
+ "link",
327
+ "meta",
328
+ "source",
329
+ "track",
330
+ "wbr"
331
+ ]);
332
+ const RAW_TEXT_TAGS = /* @__PURE__ */ new Set([
333
+ "script",
334
+ "style",
335
+ "textarea",
336
+ "title",
337
+ "xmp",
338
+ "iframe",
339
+ "noembed",
340
+ "noframes",
341
+ "noscript"
342
+ ]);
343
+ const FOREIGN_ROOTS = /* @__PURE__ */ new Set(["svg", "math"]);
344
+ function servedElementTree(html) {
345
+ const elements = [{
346
+ tag: "",
347
+ parent: -1,
348
+ child: 0
349
+ }];
350
+ const childCounts = [0];
351
+ const commentElementIndexes = [];
352
+ const nameEnds = [0];
353
+ const stack = [];
354
+ let templateDepth = 0;
355
+ let foreignDepth = 0;
356
+ let at = 0;
357
+ let lowerHtml;
358
+ while (at < html.length) {
359
+ const open = html.indexOf("<", at);
360
+ if (open < 0) break;
361
+ if (html.startsWith("<!--", open)) {
362
+ const end = html.indexOf("-->", open + 4);
363
+ at = end < 0 ? html.length : end + 3;
364
+ const data = html.slice(open + 4, end < 0 ? html.length : end);
365
+ if (templateDepth === 0 && !isArmBranchAnchorComment({
366
+ nodeType: 8,
367
+ data
368
+ })) commentElementIndexes.push(elements.length);
369
+ continue;
370
+ }
371
+ const next = html[open + 1] ?? "";
372
+ if (next === "!" || next === "?") {
373
+ const end = html.indexOf(">", open);
374
+ at = end < 0 ? html.length : end + 1;
375
+ continue;
376
+ }
377
+ const closing = next === "/";
378
+ const nameStart = closing ? open + 2 : open + 1;
379
+ const nameMatch = /^[a-zA-Z][^\s/>]*/.exec(html.slice(nameStart, nameStart + 64));
380
+ if (!nameMatch) {
381
+ at = open + 1;
382
+ continue;
383
+ }
384
+ const name = nameMatch[0];
385
+ const lower = name.toLowerCase();
386
+ const tag = foreignDepth > 0 ? name : lower;
387
+ const tagEnd = endOfTag(html, nameStart + nameMatch[0].length);
388
+ at = tagEnd + 1;
389
+ if (closing) {
390
+ const match = stack.findLastIndex((entry) => entry.tag.toLowerCase() === lower);
391
+ if (match < 0) continue;
392
+ for (const popped of stack.splice(match)) {
393
+ if (popped.tag.toLowerCase() === "template") templateDepth--;
394
+ if (FOREIGN_ROOTS.has(popped.tag.toLowerCase())) foreignDepth--;
395
+ }
396
+ continue;
397
+ }
398
+ const selfClosing = foreignDepth > 0 && html[tagEnd - 1] === "/";
399
+ const parent = stack.length ? stack[stack.length - 1].index : 0;
400
+ let index = parent;
401
+ if (templateDepth === 0) {
402
+ index = elements.push({
403
+ tag,
404
+ parent,
405
+ child: childCounts[parent]++
406
+ }) - 1;
407
+ childCounts.push(0);
408
+ nameEnds.push(nameStart + name.length);
409
+ }
410
+ if (VOID_TAGS.has(lower) || selfClosing) continue;
411
+ if (RAW_TEXT_TAGS.has(lower)) {
412
+ const close = (lowerHtml ??= html.toLowerCase()).indexOf(`</${lower}`, at);
413
+ at = close < 0 ? html.length : endOfTag(html, close + 2 + lower.length) + 1;
414
+ continue;
415
+ }
416
+ if (lower === "template") templateDepth++;
417
+ if (FOREIGN_ROOTS.has(lower)) foreignDepth++;
418
+ stack.push({
419
+ tag,
420
+ index
421
+ });
422
+ }
423
+ return {
424
+ elements,
425
+ childCounts,
426
+ commentElementIndexes,
427
+ nameEnds
428
+ };
429
+ }
430
+ function endOfTag(html, from) {
431
+ let quote = "";
432
+ for (let at = from; at < html.length; at++) {
433
+ const char = html[at];
434
+ if (quote) {
435
+ if (char === quote) quote = "";
436
+ } else if (char === "\"" || char === "'") quote = char;
437
+ else if (char === ">") return at;
438
+ }
439
+ return html.length - 1;
440
+ }
441
+ /**
442
+ * The attribute value for a container whose inner html is `containerHtml`, or
443
+ * undefined when the html holds fewer elements than the locators name.
444
+ * One entry per located element and each of its ancestors, so every entry is
445
+ * one step from its parent; the format is documented on PROTOCOL_LOCATOR_PATHS_DIGITS.
446
+ */
447
+ function servedLocatorPaths(containerHtml, locators) {
448
+ if (locators.length === 0) return void 0;
449
+ const { elements, childCounts } = servedElementTree(containerHtml);
450
+ const chain = /* @__PURE__ */ new Set();
451
+ for (const { index } of locators) {
452
+ if (index >= elements.length) return void 0;
453
+ for (let at = index; at > 0 && !chain.has(at); at = elements[at].parent) chain.add(at);
454
+ }
455
+ if (chain.size === 0) return void 0;
456
+ const tags = [];
457
+ const parents = [];
458
+ const stack = [0];
459
+ let entries = "";
460
+ let previous = 0;
461
+ for (const index of [...chain].sort((left, right) => left - right)) {
462
+ const { tag, parent, child } = elements[index];
463
+ let up = 0;
464
+ while (stack[stack.length - 1] !== parent) {
465
+ stack.pop();
466
+ up++;
467
+ }
468
+ if (!tags.includes(tag)) tags.push(tag);
469
+ if (!parents.includes(parent)) parents.push(parent);
470
+ entries += pathNumber(up) + pathNumber(index - previous) + pathNumber(child) + pathNumber(tags.indexOf(tag));
471
+ stack.push(index);
472
+ previous = index;
473
+ }
474
+ return `${elements.length}${tags.join(",")}|${entries}|${parents.map((parent) => pathNumber(childCounts[parent])).join("")}`;
475
+ }
476
+ function pathNumber(value) {
477
+ let digits = "";
478
+ for (; value >= 32; value = Math.floor(value / 32)) digits += PROTOCOL_LOCATOR_PATHS_DIGITS[32 + value % 32];
479
+ return digits + PROTOCOL_LOCATOR_PATHS_DIGITS[value];
480
+ }
481
+ //#endregion
273
482
  //#region ../web/src/render-to-string.ts
483
+ const MARKLESS_COMPONENT_PART_BRAND = "marklessComponentPart";
274
484
  async function assemblePrerenderPageParts(component, output, options) {
275
485
  const { state, view } = await prepareSsrResumeRecords(output);
276
486
  const browserTriggers = hasBrowserTriggers(view, state);
@@ -280,27 +490,57 @@ async function assemblePrerenderPageParts(component, output, options) {
280
490
  const selfWake = hasUnsettledAsyncBoundaryRunner(view, state);
281
491
  const boot = artifactPrerenderBoot(component);
282
492
  const settle = options.armEmission && selfWake ? boot?.settle : void 0;
283
- 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) : "";
493
+ 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) : "";
284
494
  return {
285
495
  head: [
286
496
  renderStorageSeedScript(artifactStorageSeeds(component), options.nonce),
287
497
  renderHeadInjections(artifactHeadInjections(component), options.nonce),
288
498
  renderModulePreloadLinks(modulePreloads, options.nonce)
289
499
  ].filter(Boolean).join(""),
290
- container: [
291
- `<div${renderContainerAttributes(options.containerId)}>`,
500
+ container: renderContainer(options.containerId, [
292
501
  output.html,
293
- options.armEmission ?? "",
294
- resumerScript,
295
- "</div>"
296
- ].filter(Boolean).join("")
502
+ options.armEmission,
503
+ resumerScript
504
+ ], resumerScript ? view.locators : [])
297
505
  };
298
506
  }
299
507
  async function renderSsrOutput(component, props, renderContext) {
300
- if (typeof component === "function") return component(props, renderContext);
301
- if (component && typeof component.renderSsr === "function") return component.renderSsr(props, renderContext);
508
+ assertPageRenderable(component);
509
+ globalThis.__marklessRosterResume ??= () => import("./roster-resume-CpphsFl_.js");
510
+ const context = marklessSsrRosterPositionContext(renderContext);
511
+ if (typeof component === "function") return marklessSsrRosterCounted(context, await marklessSsrDeferredCounted(context, await component(props, context)));
512
+ if (component && typeof component.renderSsr === "function") return marklessSsrRosterCounted(context, await marklessSsrDeferredCounted(context, await component.renderSsr(props, context)));
302
513
  throw new TypeError("renderToString(App) requires a compiled TSRX artifact.");
303
514
  }
515
+ /**
516
+ * The count-spending expressions this render handed over unevaluated. They are
517
+ * answered first: the placeholder resolver that runs after them only has plain
518
+ * count reads left to replace.
519
+ */
520
+ async function marklessSsrDeferredCounted(renderContext, surface) {
521
+ const seeds = renderContext?.sharedSeeds;
522
+ const deferred = marklessRosterPositions(seeds)?.deferred;
523
+ if (!deferred || deferred.length === 0) return surface;
524
+ const roster = await globalThis.__marklessRosterResume?.();
525
+ if (!roster) throw new Error("MARKLESS_ROSTER_COUNT_UNRESOLVED");
526
+ return roster.marklessResolveDeferredCounts(surface, deferred);
527
+ }
528
+ /**
529
+ * Refuses a bare component part used AS A PAGE. `renderSsrOutput` is the one
530
+ * place a surface becomes a served page - composition reaches a part through
531
+ * `marklessSsrComponentPart` and never comes here - so the refusal costs
532
+ * composition nothing while a part-as-page can no longer be served inert.
533
+ */
534
+ function assertPageRenderable(component) {
535
+ const partName = componentPartName(component);
536
+ if (partName === void 0) return;
537
+ throw new Error(`MARKLESS_COMPONENT_PART_AS_PAGE: "${partName}" is published as a bare render part, not a page. A non-root export carries none of its module's page wiring (no resume module, no preloads, no head injections), so a page rendered from it is served complete and inert: no client runtime is ever fetched and no gesture can dispatch. Render "${partName}" inside a page, or make it the module's root export - the root is published merged with the module surface.`);
538
+ }
539
+ function componentPartName(component) {
540
+ if (typeof component !== "object" || component === null) return void 0;
541
+ const name = component[MARKLESS_COMPONENT_PART_BRAND];
542
+ return typeof name === "string" ? name : void 0;
543
+ }
304
544
  function artifactResumeModuleUrl(component) {
305
545
  return typeof component === "object" ? component.resumeModuleUrl : void 0;
306
546
  }
@@ -319,18 +559,37 @@ function artifactHeadInjections(component) {
319
559
  function artifactStorageSeeds(component) {
320
560
  return typeof component === "object" ? component.storageSeeds : void 0;
321
561
  }
562
+ function artifactInlineResumerSources(component) {
563
+ return typeof component === "object" ? component.inlineResumerSources : void 0;
564
+ }
322
565
  function renderHeadInjections(injections, nonce) {
323
566
  if (!injections?.length) return "";
324
567
  return injections.filter((injection) => injection.location === "head").map((injection) => renderHeadInjection(injection, nonce)).join("");
325
568
  }
326
569
  function renderStorageSeedScript(seeds, nonce) {
327
570
  if (!seeds?.length) return "";
328
- return `<script${nonce ? ` nonce="${escapeAttribute(nonce)}"` : ""}>${escapeInlineScript(`(()=>{const s=globalThis[Symbol.for(${JSON.stringify(STORAGE_SLOT_SYMBOL_KEY)})]||={};for(const[k,d,a,f]of ${JSON.stringify(seeds.map((seed) => [
571
+ return `<script${nonce ? ` nonce="${escapeAttribute(nonce)}"` : ""}>${escapeInlineScript(`(()=>{const s=globalThis[Symbol.for(${JSON.stringify(STORAGE_SLOT_SYMBOL_KEY)})]||={},c=document.cookie.split('; ');for(const[k,d,a,f,n]of ${escapeScriptJson(JSON.stringify(seeds.map((seed) => [
329
572
  seed.slotKey,
330
573
  seed.driverKey,
331
574
  storageAttributeName(seed.driverKey),
332
- seed.fallback
333
- ]))}){let v=f;try{v=localStorage.getItem(d)??f}catch{}s[k]=v;document.documentElement.setAttribute(a,v)}})()`)}<\/script>`;
575
+ seed.fallback,
576
+ storageCookieName(seed.driverKey)
577
+ ])))}){let v=f;try{const e=c.find(e=>e.startsWith(n+'='));v=e?decodeURIComponent(e.slice(n.length+1)):localStorage.getItem(d)??f}catch{}s[k]=v;document.documentElement.setAttribute(a,v)}})()`)}<\/script>`;
578
+ }
579
+ function storageWakeSource(state, resumeModuleUrl) {
580
+ const rendered = (state.storage ?? []).flatMap((record) => {
581
+ const value = renderedCellValue(state.cells.find((cell) => cell.graphNodeId === record.graphNodeId));
582
+ return value === void 0 ? [] : [[storageSlotEntryKeyFromGraphNodeId(record.graphNodeId), value]];
583
+ });
584
+ if (rendered.length === 0) return "";
585
+ return createInlineResumerStorageWakeSource(resumeModuleUrl, STORAGE_SLOT_SYMBOL_KEY, escapeScriptJson(JSON.stringify(rendered)));
586
+ }
587
+ function renderedCellValue(cell) {
588
+ if (typeof cell?.directValue === "string") return cell.directValue;
589
+ const value = cell?.value;
590
+ if (typeof value === "string") return value;
591
+ const root = value?.root;
592
+ return typeof root === "string" ? root : void 0;
334
593
  }
335
594
  function renderHeadInjection(injection, nonce) {
336
595
  const attributes = { ...injection.attributes };
@@ -359,7 +618,7 @@ function renderModulePreloadLinks(preloads, nonce) {
359
618
  return links.join("");
360
619
  }
361
620
  function hasBrowserTriggers(view, state) {
362
- return (state.storage?.length ?? 0) > 0 || view.events.some(protocolEventDispatchesMarkless) || state.computed.some((computed) => computed.async === false && typeof computed.deriveSymbolId === "string") || view.behaviors.some((behavior) => !!behavior.symbolId) || Object.keys(view.asyncRunners ?? {}).length > 0 || view.asyncBoundaries.some((boundary) => boundary.asyncReads.some((read) => !!read.runnerSymbolId)) || (view.keyedRepeats ?? []).some((repeat) => repeat.rowEvents.length > 0) || (view.branches ?? []).some((branch) => (branch.armRecords ?? []).some((arm) => arm.events.some(protocolEventDispatchesMarkless))) || view.asyncBoundaries.some((boundary) => boundaryArmEventNames(boundary).length > 0);
621
+ return (state.storage?.length ?? 0) > 0 || view.events.some(protocolEventDispatchesMarkless) || state.computed.some((computed) => computed.async === false && typeof computed.deriveSymbolId === "string") || view.behaviors.some((behavior) => !!behavior.symbolId) || Object.keys(view.asyncRunners ?? {}).length > 0 || view.asyncBoundaries.some((boundary) => boundary.asyncReads.some((read) => !!read.runnerSymbolId)) || (view.keyedRepeats ?? []).some((repeat) => repeat.rowEvents.length > 0) || (view.branches ?? []).some((branch) => (branch.armRecords ?? []).some((arm) => arm.events.some(protocolEventDispatchesMarkless)) || branchServedArmEventNames(branch).length > 0) || view.asyncBoundaries.some((boundary) => boundaryArmEventNames(boundary).length > 0);
363
622
  }
364
623
  function hasUnsettledAsyncBoundaryRunner(view, state) {
365
624
  const runners = { ...view.asyncRunners };
@@ -385,19 +644,46 @@ function boundaryArmEventNames(boundary) {
385
644
  if (!armRecords || Array.isArray(armRecords)) return [];
386
645
  return [...(armRecords.events ?? []).filter(protocolEventDispatchesMarkless).map((event) => event.eventName), ...(armRecords.keyedRepeats ?? []).flatMap((repeat) => repeat.rowEvents.map((event) => event.eventName))];
387
646
  }
647
+ function branchServedArmEventNames(branch) {
648
+ const armRecords = branch.servedArmRecords;
649
+ if (!armRecords) return [];
650
+ return [...armRecords.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName), ...(armRecords.keyedRepeats ?? []).flatMap((repeat) => repeat.rowEvents.map((event) => event.eventName))];
651
+ }
652
+ function eventHostIndexes(view, eventName) {
653
+ const hosts = new Set(view.events.filter((event) => event.eventName === eventName).map((event) => event.hostNodeId));
654
+ return view.locators.filter((locator) => hosts.has(locator.hostNodeId)).map((locator) => locator.index);
655
+ }
656
+ function deferredTriggerSource(view) {
657
+ const visible = eventHostIndexes(view, PROTOCOL_VISIBLE_EVENT_NAME);
658
+ const idle = eventHostIndexes(view, PROTOCOL_IDLE_EVENT_NAME$1);
659
+ if (browserEventNames({
660
+ ...view,
661
+ events: []
662
+ }).includes(PROTOCOL_IDLE_EVENT_NAME$1)) idle.push(0);
663
+ return (visible.length > 0 ? createInlineDeferTriggerSource("visible", visible) : "") + (idle.length > 0 ? createInlineDeferTriggerSource("idle", idle) : "");
664
+ }
388
665
  function browserEventNames(view) {
389
- return [...new Set([
666
+ return [.../* @__PURE__ */ new Set([
390
667
  ...view.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName),
391
668
  ...(view.keyedRepeats ?? []).flatMap((repeat) => repeat.rowEvents.map((event) => event.eventName)),
392
- ...(view.branches ?? []).flatMap((branch) => (branch.armRecords ?? []).flatMap((arm) => arm.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName))),
669
+ ...(view.branches ?? []).flatMap((branch) => [...(branch.armRecords ?? []).flatMap((arm) => arm.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName)), ...branchServedArmEventNames(branch)]),
393
670
  ...view.asyncBoundaries.flatMap(boundaryArmEventNames)
394
- ])].filter((eventName) => eventName !== "visible");
395
- }
396
- function renderContainerAttributes(containerId) {
397
- return containerId ? ` data-async-container="${escapeAttribute(containerId)}"` : " data-async-container";
398
- }
399
- function renderInlineResumerScript(source, nonce, resumeModuleUrl, selfWake, settleModuleUrl, appendSelfWakeSource = true) {
400
- return `<script data-async-resumer${nonce ? ` nonce="${escapeAttribute(nonce)}"` : ""}${resumeModuleUrl ? ` data-markless-resume-module="${escapeAttribute(resumeModuleUrl)}"` : ""}${settleModuleUrl ? ` data-markless-settle-module="${escapeAttribute(settleModuleUrl)}"` : ""}${selfWake ? " data-markless-self-wake" : ""}>${escapeInlineScript(source + (selfWake && appendSelfWakeSource ? createInlineResumerSelfWakeSource(resumeModuleUrl) : ""))}<\/script>`;
671
+ ])].filter((eventName) => eventName !== PROTOCOL_VISIBLE_EVENT_NAME);
672
+ }
673
+ function renderContainer(containerId, parts, locators) {
674
+ const inner = parts.filter(Boolean).join("");
675
+ const paths = servedLocatorPaths(inner, locators);
676
+ return `<div data-async-container${containerId ? `="${escapeAttribute(containerId)}"` : ""}${paths ? ` ${PROTOCOL_LOCATOR_PATHS_ATTRIBUTE}="${paths}"` : ""}>${inner}</div>`;
677
+ }
678
+ function renderInlineResumerScript(source, nonce, resumeModuleUrl, selfWake, settleModuleUrl, appendSelfWakeSource = true, overlayPrimer = false, appendedSource = "", deferFactory) {
679
+ const nonceAttribute = nonce ? ` nonce="${escapeAttribute(nonce)}"` : "";
680
+ const resumeModuleAttribute = resumeModuleUrl ? ` data-markless-resume-module="${escapeAttribute(resumeModuleUrl)}"` : "";
681
+ const settleModuleAttribute = settleModuleUrl ? ` data-markless-settle-module="${escapeAttribute(settleModuleUrl)}"` : "";
682
+ const selfWakeAttribute = selfWake ? " data-markless-self-wake" : "";
683
+ const selfWakeSource = selfWake && appendSelfWakeSource ? createInlineResumerSelfWakeSource(resumeModuleUrl) : "";
684
+ const overlayPrimerSource = overlayPrimer ? createInlineResumerOverlayPrimerSource(resumeModuleUrl) : "";
685
+ const [first, ...rest] = (source + selfWakeSource + overlayPrimerSource + appendedSource).split(inlineDeferSource());
686
+ return `<script data-async-resumer${nonceAttribute}${resumeModuleAttribute}${settleModuleAttribute}${selfWakeAttribute}>${escapeInlineScript(rest.length ? `${first}${inlineDeferSource(deferFactory)}${rest.join("globalThis.__mDefer")}` : first)}<\/script>`;
401
687
  }
402
688
  function escapeAttribute(value) {
403
689
  return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
@@ -427,7 +713,8 @@ async function emitPrerenderedPage(input) {
427
713
  const html = await readFile(htmlFile, "utf8");
428
714
  const placeholder = "<div id=\"app\"></div>";
429
715
  if (!html.includes(placeholder)) throw new Error("MARKLESS_PRERENDER_CONTAINER_MISSING: expected exact #app build placeholder");
430
- await writeFile(htmlFile, (page.head ? html.replace("</head>", `${page.head}</head>`) : html).replace(placeholder, page.container));
716
+ const withHead = page.head ? html.replace("</head>", `${page.head}</head>`) : html;
717
+ await writeFile(htmlFile, withHead.replace(placeholder, page.container));
431
718
  }
432
719
  const SENTINEL_OPEN = "";
433
720
  const SENTINEL_CLOSE = "";
@@ -911,6 +1198,101 @@ async function withBuiltPrerenderPage(input, read) {
911
1198
  }
912
1199
  }
913
1200
  //#endregion
1201
+ //#region src/build/deferred-runtime.ts
1202
+ /**
1203
+ * Deferred packs for runtime no compiled demand names: each such dynamic-import target, plus what
1204
+ * only such targets reach. Modules reached from the same targets share one pack, so each target
1205
+ * stays its own chunk. A target other code imports statically still gets a pack: that importer
1206
+ * loads it through its static edge, while no preload plan follows a dynamic edge into it.
1207
+ */
1208
+ function deferredRuntimePacks(input) {
1209
+ const packs = /* @__PURE__ */ new Map();
1210
+ if (input.undemanded.size === 0) return packs;
1211
+ const undemanded = withUndemandedReExportDoors(input.modules, input.undemanded);
1212
+ const reach = (roots, skipUndemanded) => {
1213
+ const reached = /* @__PURE__ */ new Set();
1214
+ const pending = [...roots];
1215
+ while (pending.length) {
1216
+ const id = pending.pop();
1217
+ if (reached.has(id)) continue;
1218
+ reached.add(id);
1219
+ const module = input.modules.get(id);
1220
+ if (!module) continue;
1221
+ pending.push(...module.dependencies);
1222
+ for (const target of module.dynamicDependencies) if (!skipUndemanded || !undemanded.has(target)) pending.push(target);
1223
+ }
1224
+ return reached;
1225
+ };
1226
+ const lazy = reach(undemanded, false);
1227
+ const kept = reach([...input.modules.keys()].filter((id) => !lazy.has(id)), true);
1228
+ const dynamicTargets = /* @__PURE__ */ new Set();
1229
+ const behindUndemanded = /* @__PURE__ */ new Set();
1230
+ for (const [id, module] of input.modules) {
1231
+ for (const target of module.dynamicDependencies) dynamicTargets.add(target);
1232
+ if (undemanded.has(id)) for (const dependency of module.dependencies) behindUndemanded.add(dependency);
1233
+ }
1234
+ const reachedBy = /* @__PURE__ */ new Map();
1235
+ for (const target of [...undemanded].sort()) {
1236
+ if (behindUndemanded.has(target) && !dynamicTargets.has(target)) continue;
1237
+ const label = runtimeModuleIdFromOrigin(target.split("?")[0]) ?? "runtime";
1238
+ for (const id of reach([target], false)) {
1239
+ if (!input.modules.has(id) || kept.has(id) && !undemanded.has(id)) continue;
1240
+ const labels = reachedBy.get(id) ?? [];
1241
+ if (!labels.includes(label)) labels.push(label);
1242
+ reachedBy.set(id, labels);
1243
+ }
1244
+ }
1245
+ for (const [id, labels] of reachedBy) packs.set(id, `${MARKLESS_DEFERRED_PACK}-${labels.join("+").replace(/[^\w+-]/g, "-")}`);
1246
+ return packs;
1247
+ }
1248
+ function deferredRuntimePlugin(demandMaps) {
1249
+ let packs = /* @__PURE__ */ new Map();
1250
+ return {
1251
+ name: "markless:deferred-runtime",
1252
+ options(input) {
1253
+ return input.preserveEntrySignatures === false ? null : {
1254
+ ...input,
1255
+ preserveEntrySignatures: "allow-extension"
1256
+ };
1257
+ },
1258
+ buildEnd(error) {
1259
+ packs = /* @__PURE__ */ new Map();
1260
+ if (error) return;
1261
+ const modules = /* @__PURE__ */ new Map();
1262
+ for (const id of this.getModuleIds()) {
1263
+ const info = this.getModuleInfo(id);
1264
+ if (!info || "isExternal" in info && info.isExternal) continue;
1265
+ modules.set(id, {
1266
+ dependencies: info.importedIds,
1267
+ dynamicDependencies: info.dynamicallyImportedIds,
1268
+ reExportsOnly: isReExportDoor(info)
1269
+ });
1270
+ }
1271
+ packs = deferredRuntimePacks({
1272
+ modules,
1273
+ undemanded: undemandedRuntimeModules({
1274
+ demandMaps: demandMaps(),
1275
+ moduleIds: modules.keys()
1276
+ })
1277
+ });
1278
+ },
1279
+ outputOptions(output) {
1280
+ if (typeof output.codeSplitting !== "object") return null;
1281
+ return {
1282
+ ...output,
1283
+ codeSplitting: {
1284
+ ...output.codeSplitting,
1285
+ groups: [{
1286
+ name: (id) => packs.get(id) ?? null,
1287
+ priority: 1e3,
1288
+ includeDependenciesRecursively: false
1289
+ }, ...output.codeSplitting.groups ?? []]
1290
+ }
1291
+ };
1292
+ }
1293
+ };
1294
+ }
1295
+ //#endregion
914
1296
  //#region src/vite/dev-tags.ts
915
1297
  function createDevTags() {
916
1298
  const tags = [];
@@ -1022,7 +1404,7 @@ if (window.__MARKLESS_DEV_ERROR__) show(window.__MARKLESS_DEV_ERROR__);
1022
1404
  }
1023
1405
  //#endregion
1024
1406
  //#region src/vite/environment.ts
1025
- const UNMANAGED_VITE_ENVIRONMENTS = new Set(["nitro"]);
1407
+ const UNMANAGED_VITE_ENVIRONMENTS = /* @__PURE__ */ new Set(["nitro"]);
1026
1408
  function viteEnvironmentName(environment, options = {}) {
1027
1409
  if (environment === "client") return options.clientEnvironment ?? "client";
1028
1410
  if (environment === "server") return options.serverEnvironment ?? "ssr";
@@ -1048,6 +1430,19 @@ function isUnmanagedViteEnvironment(environment) {
1048
1430
  function transformMarklessRequest(server, url, environment, options) {
1049
1431
  return server.environments[viteEnvironmentName(environment, options)]?.transformRequest(url);
1050
1432
  }
1433
+ const serverModuleRunners = /* @__PURE__ */ new WeakMap();
1434
+ function serverModuleRunner(server, environmentName) {
1435
+ const environment = server.environments[environmentName];
1436
+ if (!environment || !isRunnableDevEnvironment(environment)) throw new Error(`MARKLESS_DEV_MODULE_RUNNER_UNAVAILABLE: ${environmentName}`);
1437
+ const byName = serverModuleRunners.get(server) ?? /* @__PURE__ */ new Map();
1438
+ serverModuleRunners.set(server, byName);
1439
+ const existing = byName.get(environmentName);
1440
+ if (existing) return existing;
1441
+ const runner = createServerModuleRunner(environment);
1442
+ byName.set(environmentName, runner);
1443
+ server.httpServer?.once("close", () => void runner.close());
1444
+ return runner;
1445
+ }
1051
1446
  function hasInProcessModuleRunner(environment) {
1052
1447
  return !!environment && isRunnableDevEnvironment(environment);
1053
1448
  }
@@ -1262,11 +1657,13 @@ function createViteHmr(options) {
1262
1657
  reloadModuleRunner();
1263
1658
  return [];
1264
1659
  }
1265
- const files = changedFiles(ctx.modules ?? []);
1660
+ const modules = new Set(ctx.modules ?? []);
1661
+ if (ctx.file) for (const target of targets.keys()) for (const module of target.moduleGraph?.getModulesByFile?.(ctx.file) ?? []) modules.add(module);
1662
+ const files = changedFiles([...modules]);
1266
1663
  const root = server?.config?.root;
1267
1664
  if (ctx.file && SOURCE_FILE_EXTENSION.test(ctx.file)) {
1268
1665
  const prefix = root && `${root}/`;
1269
- files.add(prefix && ctx.file.startsWith(prefix) ? `/${ctx.file.slice(prefix.length)}` : ctx.file);
1666
+ files.set(parsePath(ctx.file).pathname, prefix && ctx.file.startsWith(prefix) ? `/${ctx.file.slice(prefix.length)}` : ctx.file);
1270
1667
  }
1271
1668
  if (!files.size) return;
1272
1669
  let sendMessages = true;
@@ -1302,8 +1699,8 @@ function createViteHmr(options) {
1302
1699
  const invalidationEnvironments = [...targets.keys()];
1303
1700
  const invalidationScopes = generatedModuleScopes(targets);
1304
1701
  const invalidatedGeneratedIds = /* @__PURE__ */ new Set();
1305
- for (const file of files) {
1306
- const candidates = editedSource !== void 0 && ctx.file ? [ctx.file] : hmrCandidates(file, ctx.file);
1702
+ for (const [sourceId] of files) {
1703
+ const candidates = editedSource !== void 0 && ctx.file ? [ctx.file] : hmrCandidates(sourceId, ctx.file && SOURCE_FILE_EXTENSION.test(ctx.file) ? ctx.file : void 0);
1307
1704
  for (const candidate of candidates) for (const scope of invalidationScopes) {
1308
1705
  const invalidatedIds = await options.invalidateGeneratedModules?.(candidate, scope, candidate === ctx.file ? editedSource : void 0);
1309
1706
  for (const id of invalidatedIds ?? []) {
@@ -1373,7 +1770,7 @@ function clientHot(server, options, environment) {
1373
1770
  return environment.hot;
1374
1771
  }
1375
1772
  function invalidationTargets(server, options, environment, env) {
1376
- const targets = new Map([[environment, env]]);
1773
+ const targets = /* @__PURE__ */ new Map([[environment, env]]);
1377
1774
  const clientEnvironment = server?.environments?.[options.clientEnvironment];
1378
1775
  if (clientEnvironment) targets.set(clientEnvironment, "client");
1379
1776
  for (const [name, candidate] of Object.entries(server?.environments ?? {})) {
@@ -1396,10 +1793,10 @@ function moduleRunnerHots(targets, clientChannel) {
1396
1793
  return [...hots];
1397
1794
  }
1398
1795
  function changedFiles(modules) {
1399
- const files = /* @__PURE__ */ new Set();
1796
+ const files = /* @__PURE__ */ new Map();
1400
1797
  for (const module of modules) for (const item of [module, ...module.importers ?? []]) {
1401
1798
  const url = sourceUrl(item);
1402
- if (url) files.add(url);
1799
+ if (url) files.set(parsePath(item.id ?? item.file ?? url).pathname, url);
1403
1800
  }
1404
1801
  return files;
1405
1802
  }
@@ -1409,12 +1806,12 @@ function sourceUrl(module) {
1409
1806
  return null;
1410
1807
  }
1411
1808
  function hmrCandidates(file, absoluteFile) {
1412
- const candidates = new Set([file]);
1809
+ const candidates = /* @__PURE__ */ new Set([file]);
1413
1810
  if (absoluteFile) candidates.add(absoluteFile);
1414
1811
  return candidates;
1415
1812
  }
1416
1813
  function firstChangedFile(files) {
1417
- for (const file of files) return file;
1814
+ for (const file of files.values()) return file;
1418
1815
  }
1419
1816
  //#endregion
1420
1817
  //#region src/vite/dev-prerender.ts
@@ -1475,7 +1872,8 @@ function createDevPrerender(input) {
1475
1872
  } catch (error) {
1476
1873
  const environment = server?.environments[input.serverEnvironment];
1477
1874
  input.reportError(environment, error);
1478
- return injectDevClients(renderMarklessDevErrorDocument(normalizeMarklessDevError(error, { id: input.entry }), { base: input.base }), input.base);
1875
+ const payload = normalizeMarklessDevError(error, { id: input.entry });
1876
+ return injectDevClients(renderMarklessDevErrorDocument(payload, { base: input.base }), input.base);
1479
1877
  }
1480
1878
  },
1481
1879
  configureServer(nextServer) {
@@ -1486,6 +1884,49 @@ function createDevPrerender(input) {
1486
1884
  };
1487
1885
  }
1488
1886
  //#endregion
1887
+ //#region src/vite/dev-server-externals.ts
1888
+ function withDevServerExternals(context) {
1889
+ const config = context.environment?.config;
1890
+ if (config?.consumer !== "server") return context;
1891
+ const noExternal = config.resolve?.noExternal;
1892
+ const resolve = async (source, importer, options) => {
1893
+ const resolved = await context.resolve(source, importer, options);
1894
+ if (!isBareSpecifier(source) || matchesNoExternal(noExternal, source)) return resolved;
1895
+ const id = typeof resolved === "string" ? resolved : resolved?.id;
1896
+ if (!id || !isBuiltDependency(pathname(String(id)))) return resolved;
1897
+ return {
1898
+ ...typeof resolved === "object" ? resolved : {},
1899
+ id: String(id),
1900
+ external: true
1901
+ };
1902
+ };
1903
+ return new Proxy(context, { get(target, property) {
1904
+ if (property === "resolve") return resolve;
1905
+ const value = Reflect.get(target, property, target);
1906
+ return typeof value === "function" ? value.bind(target) : value;
1907
+ } });
1908
+ }
1909
+ function isBareSpecifier(source) {
1910
+ return !source.startsWith(".") && !isAbsolute(source) && !source.startsWith("\0") && !source.startsWith("virtual:");
1911
+ }
1912
+ function isBuiltDependency(id) {
1913
+ return id.includes("/node_modules/") && /\.[cm]?js$/.test(id);
1914
+ }
1915
+ function matchesNoExternal(noExternal, source) {
1916
+ if (noExternal === true) return true;
1917
+ if (noExternal === void 0) return false;
1918
+ return (typeof noExternal === "string" || noExternal instanceof RegExp ? [noExternal] : noExternal).some((pattern) => typeof pattern === "string" ? source === pattern || source.startsWith(`${pattern}/`) : pattern.test(source));
1919
+ }
1920
+ //#endregion
1921
+ //#region src/vite/dev-runtime-imports.ts
1922
+ function installDevRuntimeImportResolution(server, clientEnvironment) {
1923
+ for (const [name, environment] of Object.entries(server.environments ?? {})) {
1924
+ if (name === clientEnvironment || typeof environment.fetchModule !== "function") continue;
1925
+ const fetchModule = environment.fetchModule.bind(environment);
1926
+ environment.fetchModule = (id, importer, options) => fetchModule(marklessRuntimeSpecifierId(id) ?? id, importer, options);
1927
+ }
1928
+ }
1929
+ //#endregion
1489
1930
  //#region src/vite/index.ts
1490
1931
  const MARKLESS_SKIP_DUPLICATE_BUILDS = Symbol("markless-skip-duplicate-builds");
1491
1932
  const TSRX_INPUT_FILE = /\.tsrx(?:[?#].*)?$/;
@@ -1494,7 +1935,12 @@ function markless(options = {}) {
1494
1935
  const bundleGraphAdders = /* @__PURE__ */ new Set();
1495
1936
  const transformedTsrxSources = /* @__PURE__ */ new Map();
1496
1937
  const prerenderRecordsBySource = /* @__PURE__ */ new Map();
1497
- const rolldownOptions = { ...options };
1938
+ const { experimentalNativePacking: _deprecatedPacking, ...rest } = options;
1939
+ const rolldownOptions = {
1940
+ ...rest,
1941
+ packing: nativePackingEnabled(options),
1942
+ chunkImportMap: options.experimentalNativePacking === true
1943
+ };
1498
1944
  const prerender = process.env.MARKLESS_PRERENDER === "1";
1499
1945
  const explicitPrerenderWake = process.env.MARKLESS_PRERENDER_WAKE;
1500
1946
  rolldownOptions.prerender = false;
@@ -1551,12 +1997,17 @@ function markless(options = {}) {
1551
1997
  __MARKLESS_DEV_ENABLED__: devDefine
1552
1998
  };
1553
1999
  configDefaults(config, options, rolldownOptions);
2000
+ if (devEnabled) {
2001
+ includeOptimizedDeps(config, [RESUME_ENTRY_SPECIFIER, STORAGE_FREE_RESUME_ENTRY_SPECIFIER]);
2002
+ excludeSourceShippedDeps(config);
2003
+ }
1554
2004
  if (prerender || stagePrerenderWake) {
1555
2005
  prerenderEntry = ssrTsrxInput(config, options);
1556
2006
  rolldownOptions.prerender = prerender && prerenderEntry !== null;
1557
2007
  }
1558
2008
  },
1559
2009
  configResolved(resolvedConfig) {
2010
+ if (options.experimentalNativePacking !== void 0) resolvedConfig.logger.warn(DEPRECATED_NATIVE_PACKING_WARNING);
1560
2011
  resolvedRoot = resolvedConfig.root;
1561
2012
  clientOutDir = resolvedConfig.build?.outDir ?? "dist";
1562
2013
  const serve = resolvedConfig.command === "serve";
@@ -1636,9 +2087,10 @@ function markless(options = {}) {
1636
2087
  }
1637
2088
  },
1638
2089
  configureServer(server) {
1639
- server.config.logger?.info("markless diagnostics available - window.__MARKLESS_DEBUG__ records containers, lifecycles, and event routing; markless debugging playbook: run pnpm doctor, or read agent/markless.md in the installed @markless/core package.");
2090
+ server.config.logger?.info(`markless diagnostics available - window.__MARKLESS_DEBUG__ records containers, lifecycles, and event routing; ${DEBUGGING_PLAYBOOK_HINT}.`);
1640
2091
  rolldownOptions.devServer = {
1641
2092
  transformRequest: (url, environment) => transformMarklessRequest(server, url, environment, options),
2093
+ importModule: (source) => serverModuleRunner(server, viteEnvironmentName("server", options)).import(source),
1642
2094
  invalidateModule: (id, environment) => {
1643
2095
  const target = server.environments[viteEnvironmentName(environment, options)];
1644
2096
  const module = target?.moduleGraph?.getModuleById?.(id);
@@ -1648,6 +2100,7 @@ function markless(options = {}) {
1648
2100
  }
1649
2101
  };
1650
2102
  hmr.configureServer(server);
2103
+ installDevRuntimeImportResolution(server, viteEnvironmentName("client", options));
1651
2104
  devPrerender?.configureServer(server);
1652
2105
  },
1653
2106
  transformIndexHtml(html) {
@@ -1679,7 +2132,8 @@ function markless(options = {}) {
1679
2132
  transform: { async handler(code, id, transformOptions) {
1680
2133
  if (rolldownOptions.dev === true && TSRX_INPUT_FILE.test(id)) transformedTsrxSources.set(parsePath(id).pathname, code);
1681
2134
  try {
1682
- return await runHook(basePlugin.transform, this, code, id, transformOptions);
2135
+ const context = rolldownOptions.dev === true ? withDevServerExternals(this) : this;
2136
+ return await runHook(basePlugin.transform, context, code, id, transformOptions);
1683
2137
  } catch (error) {
1684
2138
  if (rolldownOptions.dev === true && TSRX_INPUT_FILE.test(id)) {
1685
2139
  const environment = this.environment;
@@ -1693,7 +2147,52 @@ function markless(options = {}) {
1693
2147
  return hmr.hotUpdate(this.environment, ctx);
1694
2148
  }
1695
2149
  };
1696
- return [marklessPlugin];
2150
+ return [
2151
+ marklessPlugin,
2152
+ {
2153
+ name: "markless:shared-render-data-reach",
2154
+ enforce: "pre",
2155
+ resolveId: {
2156
+ filter: { id: /[?&]markless-reached-from=/ },
2157
+ async handler(source, importer) {
2158
+ const shared = sharedReachedRenderDataRequest(source);
2159
+ return shared ? await this.resolve(shared, importer, { skipSelf: true }) : null;
2160
+ }
2161
+ }
2162
+ },
2163
+ {
2164
+ name: "markless:init-facade-imports",
2165
+ apply: "build",
2166
+ enforce: "pre",
2167
+ applyToEnvironment(environment) {
2168
+ return environment.config.consumer === "client";
2169
+ },
2170
+ generateBundle: {
2171
+ order: "post",
2172
+ async handler(_options, bundle) {
2173
+ await prefetchChunkParses(Object.values(bundle).filter((output) => output.type === "chunk" && output.code.includes("import(")));
2174
+ collapseInitFacadeImports(bundle);
2175
+ unwrapAsyncImportWrappers(bundle);
2176
+ }
2177
+ }
2178
+ },
2179
+ ...nativePackingEnabled(options) ? nativePackingPlugins(() => resolvedRoot, () => basePlugin.api.runtimeDemandMaps(), () => basePlugin.api.runtimeDemandSources()).map((plugin) => ({
2180
+ ...plugin,
2181
+ apply: "build",
2182
+ enforce: "post",
2183
+ sharedDuringBuild: true,
2184
+ applyToEnvironment(environment) {
2185
+ return environment.config.consumer === "client";
2186
+ }
2187
+ })) : [{
2188
+ ...deferredRuntimePlugin(() => basePlugin.api.runtimeDemandMaps()),
2189
+ apply: "build",
2190
+ enforce: "post",
2191
+ applyToEnvironment(environment) {
2192
+ return environment.config.consumer === "client";
2193
+ }
2194
+ }]
2195
+ ];
1697
2196
  }
1698
2197
  async function buildMarklessEnvironments(builder, options) {
1699
2198
  const environments = buildEnvironments(builder, options);