@markless/bundler 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev-error-2hi-Icjn.js +176 -0
- package/dist/dev-error.d.ts +16 -16
- package/dist/dev-error.js +2 -174
- package/dist/execution-log-BL-7a77M.d.ts +17 -0
- package/dist/optimized-deps-BfzxSm6C.js +89 -0
- package/dist/preload.d.ts +44 -7
- package/dist/preload.js +3 -2
- package/dist/repeat-runtime-BDnaUYXM.js +71 -0
- package/dist/rolldown-DHkCX7vL.js +9267 -0
- package/dist/rolldown.d.ts +37 -17
- package/dist/rolldown.js +3 -3
- package/dist/roster-resume-CpphsFl_.js +427 -0
- package/dist/route-pack-groups-BXc755qH.js +2744 -0
- package/dist/shared-seed-slot-ihIVCD2S.js +113 -0
- package/dist/{types-BuooJg32.d.ts → types-iOUoceJ-.d.ts} +49 -10
- package/dist/vite.d.ts +5 -6
- package/dist/vite.js +673 -171
- package/package.json +7 -7
- package/dist/rolldown-CB2Xpf-E.js +0 -4828
- package/dist/source-module-DI20i0ZG.js +0 -1168
- package/dist/source-module-XFgOFX1c.d.ts +0 -8
package/dist/vite.js
CHANGED
|
@@ -1,21 +1,52 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { a as MARKLESS_DEV_RELOADS_EVENT, i as MARKLESS_DEV_RELOADS_ATTRIBUTE, l as normalizeMarklessDevError, n as MARKLESS_DEV_ERROR_CLIENT_ID, r as MARKLESS_DEV_ERROR_EVENT, t as MARKLESS_DEV_ERROR_CLEAR_EVENT, u as renderMarklessDevErrorDocument } from "./dev-error-2hi-Icjn.js";
|
|
2
|
+
import { N as pathname, R as sharedReachedRenderDataRequest, at as outputDefaults, ct as STORAGE_FREE_RESUME_ENTRY_SPECIFIER, kt as executionLogActivationInjection, st as RESUME_ENTRY_SPECIFIER, t as MARKLESS_DEFERRED_PACK } from "./route-pack-groups-BXc755qH.js";
|
|
3
|
+
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";
|
|
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 { join, resolve } from "pathe";
|
|
7
|
+
import { ASYNC_PROTOCOL_VERSION, PROTOCOL_CONTAINER_HOST_NODE_ID, 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";
|
|
10
|
+
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
7
11
|
import { isAbsolute as isAbsolute$1 } from "node:path";
|
|
8
12
|
import { pathToFileURL } from "node:url";
|
|
9
|
-
import {
|
|
13
|
+
import { createServerModuleRunner, isRunnableDevEnvironment } from "vite";
|
|
10
14
|
import { tmpdir } from "node:os";
|
|
11
|
-
import { PROTOCOL_EVENT_ACTION_KIND as PROTOCOL_EVENT_ACTION_KIND$1, protocolEventDispatchesMarkless } from "@markless/serializer/protocol";
|
|
15
|
+
import { PROTOCOL_CONTAINER_END_COMMENT, PROTOCOL_CONTAINER_START_COMMENT, PROTOCOL_EVENT_ACTION_KIND as PROTOCOL_EVENT_ACTION_KIND$1, PROTOCOL_IDLE_EVENT_NAME as PROTOCOL_IDLE_EVENT_NAME$1, PROTOCOL_LOCATOR_PATHS_ATTRIBUTE, PROTOCOL_VISIBLE_EVENT_NAME, protocolEventDispatchesMarkless } from "@markless/serializer/protocol";
|
|
12
16
|
import "@markless/serializer/resume-record-delta";
|
|
13
|
-
|
|
14
|
-
|
|
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
|
+
* between the page start and end markers an author's element carries. When the
|
|
21
|
+
* count differs from the one the server measured, a script outside Markless
|
|
22
|
+
* changed the page first: the root is flagged for the resume module to renumber
|
|
23
|
+
* the census, and no elements are returned, so nothing is matched by a shifted index.
|
|
24
|
+
*/
|
|
25
|
+
function marklessServedCensus(root, attribute) {
|
|
26
|
+
const live = [root];
|
|
27
|
+
const walker = document.createTreeWalker(root, 129);
|
|
28
|
+
for (let next = walker.nextNode(); next; next = walker.nextNode()) if (next.nodeType !== 8) live.push(next);
|
|
29
|
+
else if (next.data === __MARKLESS_PAGE_START__) live.length = 1;
|
|
30
|
+
else if (next.data === __MARKLESS_PAGE_END__) break;
|
|
31
|
+
root.__marklessCensus ||= live;
|
|
32
|
+
const value = root.getAttribute?.(attribute);
|
|
33
|
+
return value && parseInt(value) !== live.length ? (root.__marklessShifted = 1, []) : live;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
15
36
|
//#region ../web/src/inline/resumer.ts
|
|
37
|
+
const withPageMarkers = (source) => source.replaceAll("__MARKLESS_PAGE_START__", JSON.stringify(PROTOCOL_CONTAINER_START_COMMENT)).replaceAll("__MARKLESS_PAGE_END__", JSON.stringify(PROTOCOL_CONTAINER_END_COMMENT));
|
|
38
|
+
const servedCensusSource = () => withPageMarkers(marklessServedCensus.toString());
|
|
16
39
|
PROTOCOL_EVENT_ACTION_KIND$1.event, PROTOCOL_EVENT_ACTION_KIND$1.externalDelegate;
|
|
40
|
+
const INLINE_MODULE_LOADER_SOURCE = INLINE_DEFER_LOADER_SOURCE;
|
|
17
41
|
function createInlineResumerSelfWakeSource(resumeModuleUrl) {
|
|
18
|
-
return `;(${runInlineResumerSelfWake.toString()})(${JSON.stringify(resumeModuleUrl)});`;
|
|
42
|
+
return `;(${runInlineResumerSelfWake.toString()})(${JSON.stringify(resumeModuleUrl)},${INLINE_MODULE_LOADER_SOURCE},${inlineDeferSource()});`;
|
|
43
|
+
}
|
|
44
|
+
function createInlineResumerStorageWakeSource(resumeModuleUrl, slotSymbolKey, renderedJson) {
|
|
45
|
+
return `;(${runInlineResumerStorageWake.toString()})(${JSON.stringify(slotSymbolKey)},${renderedJson},()=>(${runInlineResumerSelfWake.toString()})(${JSON.stringify(resumeModuleUrl)},${INLINE_MODULE_LOADER_SOURCE},${inlineDeferSource()}));`;
|
|
46
|
+
}
|
|
47
|
+
function runInlineResumerStorageWake(slotSymbolKey, rendered, wake) {
|
|
48
|
+
const slot = globalThis[Symbol.for(slotSymbolKey)];
|
|
49
|
+
if (slot && rendered.some(([key, value]) => Object.hasOwn(slot, key) && slot[key] !== value)) wake();
|
|
19
50
|
}
|
|
20
51
|
/**
|
|
21
52
|
* The Escape primer, appended only to a page whose served HTML carries an
|
|
@@ -27,14 +58,14 @@ function createInlineResumerSelfWakeSource(resumeModuleUrl) {
|
|
|
27
58
|
* with no mark ships a byte-identical resumer.
|
|
28
59
|
*/
|
|
29
60
|
function createInlineResumerOverlayPrimerSource(resumeModuleUrl) {
|
|
30
|
-
return `;(${runInlineResumerOverlayPrimer.toString()})(${JSON.stringify(resumeModuleUrl)}
|
|
61
|
+
return `;(${withPageMarkers(runInlineResumerOverlayPrimer.toString())})(${JSON.stringify(resumeModuleUrl)},${INLINE_MODULE_LOADER_SOURCE});`;
|
|
31
62
|
}
|
|
32
63
|
const PRERENDER_INLINE_EVENT_NAMES_TOKEN = "__MARKLESS_PRERENDER_EVENT_NAMES__";
|
|
33
64
|
function renderPrerenderInlineResumerSource(compiled, eventNames) {
|
|
34
65
|
return compiled.replace(PRERENDER_INLINE_EVENT_NAMES_TOKEN, JSON.stringify(eventNames));
|
|
35
66
|
}
|
|
36
67
|
function createPrerenderInlineResumerSource(eventNames, resumeModuleUrl, options) {
|
|
37
|
-
const plain = `(${runPrerenderInlineResumer.toString()})(${JSON.stringify(eventNames)},${JSON.stringify(resumeModuleUrl)},u=>import(u));`;
|
|
68
|
+
const plain = `(${runPrerenderInlineResumer.toString()})(${JSON.stringify(eventNames)},${JSON.stringify(resumeModuleUrl)},u=>import(u),${servedCensusSource()},${JSON.stringify(PROTOCOL_LOCATOR_PATHS_ATTRIBUTE)});`;
|
|
38
69
|
const logging = options?.executionLog !== void 0 && options.executionLog !== "never";
|
|
39
70
|
if (!options?.debug && !logging) return plain;
|
|
40
71
|
return `{
|
|
@@ -121,73 +152,62 @@ function runPrerenderInlineResumerDebugSetup(eventNames) {
|
|
|
121
152
|
controls?.activate();
|
|
122
153
|
} catch {}
|
|
123
154
|
}
|
|
124
|
-
function runPrerenderInlineResumer(eventNames, fallbackResumeModuleUrl, loadModule) {
|
|
155
|
+
function runPrerenderInlineResumer(eventNames, fallbackResumeModuleUrl, loadModule, census, pathsAttribute) {
|
|
125
156
|
const currentScript = document.currentScript;
|
|
126
157
|
const root = currentScript?.closest("[data-async-container]");
|
|
127
158
|
const resumeModuleUrl = currentScript?.getAttribute?.("data-markless-resume-module") ?? fallbackResumeModuleUrl;
|
|
128
159
|
if (!root || !resumeModuleUrl) return;
|
|
129
160
|
let loaded;
|
|
130
|
-
|
|
161
|
+
const dispatch = (event) => {
|
|
131
162
|
root.__marklessDelegatedDispatch = true;
|
|
163
|
+
if (!root.__marklessCensus) census(root, pathsAttribute);
|
|
132
164
|
return (loaded ||= loadModule(resumeModuleUrl)).then((module) => module.resumeContainerEvent({
|
|
133
165
|
root,
|
|
134
166
|
event,
|
|
135
167
|
element: event.target,
|
|
136
168
|
eventRecord: null
|
|
137
169
|
}));
|
|
138
|
-
}
|
|
170
|
+
};
|
|
171
|
+
eventNames.map(root.__marklessListen = (eventName) => root.addEventListener(eventName, dispatch, true));
|
|
139
172
|
}
|
|
140
|
-
function runInlineResumerSelfWake(fallbackResumeModuleUrl) {
|
|
173
|
+
function runInlineResumerSelfWake(fallbackResumeModuleUrl, loadModule, defer) {
|
|
141
174
|
const currentScript = document.currentScript;
|
|
142
175
|
const root = currentScript?.closest("[data-async-container]");
|
|
143
176
|
const resumeModuleUrl = currentScript?.getAttribute?.("data-markless-resume-module") ?? fallbackResumeModuleUrl;
|
|
144
177
|
if (!root || !resumeModuleUrl) return;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
resumeModuleUrl
|
|
152
|
-
)).resumeContainerEvent({
|
|
153
|
-
root,
|
|
154
|
-
event: 0
|
|
155
|
-
});
|
|
156
|
-
}
|
|
178
|
+
defer.idle(root, async () => {
|
|
179
|
+
if (root.__asyncResumeRuntimeStarted) return;
|
|
180
|
+
root.__marklessDelegatedDispatch = true;
|
|
181
|
+
await (await (root.__mResume ||= loadModule(resumeModuleUrl))).resumeContainerEvent({
|
|
182
|
+
root,
|
|
183
|
+
event: 0
|
|
157
184
|
});
|
|
158
185
|
});
|
|
159
|
-
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", wake, { once: true });
|
|
160
|
-
else wake();
|
|
161
186
|
}
|
|
162
|
-
/**
|
|
163
|
-
* One window-level listen, from first paint, on a page that elevates something.
|
|
164
|
-
*
|
|
165
|
-
* Two facts make it necessary. A page served with an open overlay is on the
|
|
166
|
-
* stack the moment the behaviour installs, but nothing installs until the
|
|
167
|
-
* runtime wakes; and Escape is the one gesture with no route into the page -
|
|
168
|
-
* every other one reaches an authored handler through the container's own
|
|
169
|
-
* listener, while a dismissal is reported by a document listener that does not
|
|
170
|
-
* exist yet. So the first Escape on such a page would be spent waking and
|
|
171
|
-
* dismiss nothing. This listens above the container, leaves the reason where the
|
|
172
|
-
* behaviour's installer takes it, and lets the wake finish the job.
|
|
173
|
-
*
|
|
174
|
-
* Deliberately one-shot, and deliberately not the waker of first resort. The
|
|
175
|
-
* container's own capture listener runs after this one and wakes the runtime for
|
|
176
|
-
* any event the page has a record for; waking here as well would start a second
|
|
177
|
-
* runtime for one gesture. Deciding a task later is what tells the two apart.
|
|
178
|
-
*/
|
|
179
187
|
function runInlineResumerOverlayPrimer(fallbackResumeModuleUrl, loadModule) {
|
|
180
188
|
const currentScript = document.currentScript;
|
|
181
189
|
const root = currentScript?.closest("[data-async-container]");
|
|
182
190
|
const resumeModuleUrl = currentScript?.getAttribute?.("data-markless-resume-module") ?? fallbackResumeModuleUrl;
|
|
183
191
|
if (!root || !resumeModuleUrl) return;
|
|
184
192
|
const prime = (event) => {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
193
|
+
if (root.__marklessOverlayInstalled) {
|
|
194
|
+
removeEventListener("keydown", prime, true);
|
|
195
|
+
removeEventListener("pointerdown", prime, true);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (!root.querySelector("[overlay]:not([hidden])")) return;
|
|
199
|
+
if (event.key === "Escape") root.__marklessOverlayPrimedDismissal = "escape";
|
|
200
|
+
if (root.__marklessDelegatedDispatch === true) return;
|
|
201
|
+
if (!root.__marklessCensus) {
|
|
202
|
+
const census = [root];
|
|
203
|
+
const walker = document.createTreeWalker(root, 129);
|
|
204
|
+
for (let next = walker.nextNode(); next; next = walker.nextNode()) if (next.nodeType !== 8) census.push(next);
|
|
205
|
+
else if (next.data === __MARKLESS_PAGE_START__) census.length = 1;
|
|
206
|
+
else if (next.data === __MARKLESS_PAGE_END__) break;
|
|
207
|
+
root.__marklessCensus = census;
|
|
208
|
+
}
|
|
189
209
|
setTimeout(() => {
|
|
190
|
-
if (root.__marklessDelegatedDispatch) return;
|
|
210
|
+
if (root.__marklessDelegatedDispatch === true) return;
|
|
191
211
|
root.__marklessDelegatedDispatch = true;
|
|
192
212
|
loadModule(resumeModuleUrl).then((module) => module.resumeContainerEvent({
|
|
193
213
|
root,
|
|
@@ -199,75 +219,6 @@ function runInlineResumerOverlayPrimer(fallbackResumeModuleUrl, loadModule) {
|
|
|
199
219
|
addEventListener("pointerdown", prime, true);
|
|
200
220
|
}
|
|
201
221
|
//#endregion
|
|
202
|
-
//#region ../web/src/repeat-runtime.ts
|
|
203
|
-
var KeyedRepeatRuntimeError = class extends Error {
|
|
204
|
-
code = "MARKLESS_REPEAT_KEY_DUPLICATE";
|
|
205
|
-
severity = "error";
|
|
206
|
-
phase = "runtime";
|
|
207
|
-
repeatId;
|
|
208
|
-
keyPath;
|
|
209
|
-
collidingValue;
|
|
210
|
-
docsUrl;
|
|
211
|
-
constructor(diagnostic) {
|
|
212
|
-
super(diagnostic.message);
|
|
213
|
-
Object.defineProperty(this, "message", {
|
|
214
|
-
value: diagnostic.message,
|
|
215
|
-
enumerable: true,
|
|
216
|
-
configurable: true
|
|
217
|
-
});
|
|
218
|
-
this.name = "KeyedRepeatRuntimeError";
|
|
219
|
-
this.repeatId = diagnostic.repeatId;
|
|
220
|
-
this.keyPath = diagnostic.keyPath;
|
|
221
|
-
this.collidingValue = diagnostic.collidingValue;
|
|
222
|
-
this.docsUrl = diagnostic.docsUrl;
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
function validateKeyedRepeatGraphKeys(graph, view) {
|
|
226
|
-
for (const repeat of view.keyedRepeats ?? []) assertUniqueRepeatKeys(repeat, readKeyedRepeatCollection(graph, repeat));
|
|
227
|
-
}
|
|
228
|
-
async function validateKeyedRepeatPayloadKeys(input) {
|
|
229
|
-
const entries = await Promise.all(input.state.cells.map(async (cell) => [cell.graphNodeId, cell.value === void 0 ? void 0 : await deserializeGraphValueForClient(cell.value)]));
|
|
230
|
-
const cells = new Map(entries);
|
|
231
|
-
validateKeyedRepeatGraphKeys({ read(graphNodeId, path = []) {
|
|
232
|
-
return readPath(cells.get(graphNodeId), path);
|
|
233
|
-
} }, input.view);
|
|
234
|
-
}
|
|
235
|
-
function readKeyedRepeatCollection(graph, repeat) {
|
|
236
|
-
if (!repeat.collectionGraphNodeId) return [];
|
|
237
|
-
const value = graph.read(repeat.collectionGraphNodeId, repeat.collectionPath);
|
|
238
|
-
if (Array.isArray(value)) return value;
|
|
239
|
-
return Array.from(value ?? []);
|
|
240
|
-
}
|
|
241
|
-
function repeatItemKey(item, repeat) {
|
|
242
|
-
return readPath(item, repeat.keyPath);
|
|
243
|
-
}
|
|
244
|
-
function assertUniqueRepeatKeys(repeat, items) {
|
|
245
|
-
const seen = /* @__PURE__ */ new Map();
|
|
246
|
-
for (const item of items) {
|
|
247
|
-
const key = repeatItemKey(item, repeat);
|
|
248
|
-
if (seen.has(key)) throw duplicateRepeatKeyError(repeat, key);
|
|
249
|
-
seen.set(key, true);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
function duplicateRepeatKeyError(repeat, key) {
|
|
253
|
-
const source = `${repeat.itemName}.${repeat.keyPath.join(".")}`;
|
|
254
|
-
return new KeyedRepeatRuntimeError({
|
|
255
|
-
message: `MARKLESS_REPEAT_KEY_DUPLICATE: Duplicate @for key ${JSON.stringify(key)} from ${source}.`,
|
|
256
|
-
repeatId: repeat.id,
|
|
257
|
-
keyPath: repeat.keyPath,
|
|
258
|
-
collidingValue: key,
|
|
259
|
-
docsUrl: "https://markless.dev/errors/MARKLESS_REPEAT_KEY_DUPLICATE"
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
function readPath(value, path) {
|
|
263
|
-
let cursor = value;
|
|
264
|
-
for (const key of path) {
|
|
265
|
-
if (cursor == null) return void 0;
|
|
266
|
-
cursor = cursor[key];
|
|
267
|
-
}
|
|
268
|
-
return cursor;
|
|
269
|
-
}
|
|
270
|
-
//#endregion
|
|
271
222
|
//#region ../web/src/prerender/records.ts
|
|
272
223
|
async function prepareSsrResumeRecords(output) {
|
|
273
224
|
const rawState = output.state ?? emptyStatePayload();
|
|
@@ -277,7 +228,7 @@ async function prepareSsrResumeRecords(output) {
|
|
|
277
228
|
computed: serializeRuntimeAsyncSnapshots(rawState.computed ?? [])
|
|
278
229
|
};
|
|
279
230
|
const view = containerScopedView(output.view ?? emptyViewPayload());
|
|
280
|
-
await validateKeyedRepeatPayloadKeys({
|
|
231
|
+
if (view.keyedRepeats?.length) await (await import("./repeat-runtime-BDnaUYXM.js")).validateKeyedRepeatPayloadKeys({
|
|
281
232
|
state,
|
|
282
233
|
view
|
|
283
234
|
});
|
|
@@ -287,12 +238,19 @@ async function prepareSsrResumeRecords(output) {
|
|
|
287
238
|
};
|
|
288
239
|
}
|
|
289
240
|
function containerScopedView(view) {
|
|
241
|
+
const locators = view.locators.map((locator) => ({
|
|
242
|
+
...locator,
|
|
243
|
+
index: locator.index + 1
|
|
244
|
+
}));
|
|
245
|
+
if (view.keyedRepeats?.some((repeat) => repeat.parentHostNodeId === PROTOCOL_CONTAINER_HOST_NODE_ID)) locators.unshift({
|
|
246
|
+
hostNodeId: PROTOCOL_CONTAINER_HOST_NODE_ID,
|
|
247
|
+
strategy: "dom-order",
|
|
248
|
+
index: 0,
|
|
249
|
+
tagName: "*"
|
|
250
|
+
});
|
|
290
251
|
return {
|
|
291
252
|
...view,
|
|
292
|
-
locators
|
|
293
|
-
...locator,
|
|
294
|
-
index: locator.index + 1
|
|
295
|
-
}))
|
|
253
|
+
locators
|
|
296
254
|
};
|
|
297
255
|
}
|
|
298
256
|
function emptyStatePayload() {
|
|
@@ -314,6 +272,37 @@ function emptyViewPayload() {
|
|
|
314
272
|
};
|
|
315
273
|
}
|
|
316
274
|
//#endregion
|
|
275
|
+
//#region ../web/src/fns/container-region.ts
|
|
276
|
+
const CONTAINER_ATTRIBUTE = "data-async-container";
|
|
277
|
+
//#endregion
|
|
278
|
+
//#region ../web/src/fns/roster-position.ts
|
|
279
|
+
/**
|
|
280
|
+
* The server render context with the roster channels on it. One counter per
|
|
281
|
+
* render, held by the closure rather than by a module, so two page renders in
|
|
282
|
+
* one process never share a count.
|
|
283
|
+
*/
|
|
284
|
+
function marklessSsrRosterPositionContext(renderContext) {
|
|
285
|
+
const context = renderContext ?? {};
|
|
286
|
+
if (typeof context.rosterPosition === "function") return renderContext;
|
|
287
|
+
const sharedSeeds = marklessRosterPositionSeeds(context.sharedSeeds);
|
|
288
|
+
return {
|
|
289
|
+
...context,
|
|
290
|
+
sharedSeeds,
|
|
291
|
+
...marklessRosterRenderContext(marklessRosterPositions(sharedSeeds), void 0)
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* The counts this render minted, answered from the page it produced. A count is
|
|
296
|
+
* asked before the members it counts have rendered, so this is where it becomes
|
|
297
|
+
* a number — after composition, off the served view's own roster.
|
|
298
|
+
*/
|
|
299
|
+
async function marklessSsrRosterCounted(renderContext, surface) {
|
|
300
|
+
if (!marklessRosterPositions((renderContext ?? {}).sharedSeeds)?.counted) return surface;
|
|
301
|
+
const roster = await globalThis.__marklessRosterResume?.();
|
|
302
|
+
if (!roster) throw new Error("MARKLESS_ROSTER_COUNT_UNRESOLVED");
|
|
303
|
+
return roster.marklessResolveRosterCounts(surface);
|
|
304
|
+
}
|
|
305
|
+
//#endregion
|
|
317
306
|
//#region ../web/src/prerender/evaluator.ts
|
|
318
307
|
async function evaluateBuiltPageClosure(page, props) {
|
|
319
308
|
const renderContext = { prerender: true };
|
|
@@ -322,37 +311,252 @@ async function evaluateBuiltPageClosure(page, props) {
|
|
|
322
311
|
throw new TypeError("Prerender resume requires a compiled TSRX artifact.");
|
|
323
312
|
}
|
|
324
313
|
//#endregion
|
|
314
|
+
//#region ../web/src/resume-anchor-census.ts
|
|
315
|
+
function isArmBranchAnchorComment(comment) {
|
|
316
|
+
const text = comment.data ?? comment.textContent ?? "";
|
|
317
|
+
return text.startsWith("markless:arm-branch:") || text.startsWith("/markless:arm-branch:");
|
|
318
|
+
}
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region ../serializer/src/protocol-locator-paths-format.ts
|
|
321
|
+
/**
|
|
322
|
+
* The value of PROTOCOL_LOCATOR_PATHS_ATTRIBUTE: the served element count in decimal, the tag
|
|
323
|
+
* table joined by `,`, `|`, then for every located element and each of its ancestors, in tree
|
|
324
|
+
* order, four numbers: how many levels to step up from the previous entry to reach its parent (the
|
|
325
|
+
* container is 0), its DOM-order index as a delta from the previous entry, its place among the
|
|
326
|
+
* parent's element children, and its tag's place in the table; then `|` and each parent's served
|
|
327
|
+
* element-child count, in the order entries first name that parent. Numbers are written low five
|
|
328
|
+
* bits first: a digit from the first 32 here ends a number, one from the last 32 carries.
|
|
329
|
+
*/
|
|
330
|
+
const PROTOCOL_LOCATOR_PATHS_DIGITS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
|
|
331
|
+
//#endregion
|
|
332
|
+
//#region ../web/src/locator-paths.ts
|
|
333
|
+
const VOID_TAGS = /* @__PURE__ */ new Set([
|
|
334
|
+
"area",
|
|
335
|
+
"base",
|
|
336
|
+
"br",
|
|
337
|
+
"col",
|
|
338
|
+
"embed",
|
|
339
|
+
"hr",
|
|
340
|
+
"img",
|
|
341
|
+
"input",
|
|
342
|
+
"link",
|
|
343
|
+
"meta",
|
|
344
|
+
"source",
|
|
345
|
+
"track",
|
|
346
|
+
"wbr"
|
|
347
|
+
]);
|
|
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
|
+
const FOREIGN_ROOTS = /* @__PURE__ */ new Set(["svg", "math"]);
|
|
360
|
+
function servedElementTree(html) {
|
|
361
|
+
const elements = [{
|
|
362
|
+
tag: "",
|
|
363
|
+
parent: -1,
|
|
364
|
+
child: 0
|
|
365
|
+
}];
|
|
366
|
+
const childCounts = [0];
|
|
367
|
+
const commentElementIndexes = [];
|
|
368
|
+
const nameEnds = [0];
|
|
369
|
+
const stack = [];
|
|
370
|
+
let templateDepth = 0;
|
|
371
|
+
let foreignDepth = 0;
|
|
372
|
+
let at = 0;
|
|
373
|
+
let lowerHtml;
|
|
374
|
+
while (at < html.length) {
|
|
375
|
+
const open = html.indexOf("<", at);
|
|
376
|
+
if (open < 0) break;
|
|
377
|
+
if (html.startsWith("<!--", open)) {
|
|
378
|
+
const end = html.indexOf("-->", open + 4);
|
|
379
|
+
at = end < 0 ? html.length : end + 3;
|
|
380
|
+
const data = html.slice(open + 4, end < 0 ? html.length : end);
|
|
381
|
+
if (templateDepth === 0 && !isArmBranchAnchorComment({
|
|
382
|
+
nodeType: 8,
|
|
383
|
+
data
|
|
384
|
+
})) commentElementIndexes.push(elements.length);
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
const next = html[open + 1] ?? "";
|
|
388
|
+
if (next === "!" || next === "?") {
|
|
389
|
+
const end = html.indexOf(">", open);
|
|
390
|
+
at = end < 0 ? html.length : end + 1;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
const closing = next === "/";
|
|
394
|
+
const nameStart = closing ? open + 2 : open + 1;
|
|
395
|
+
const nameMatch = /^[a-zA-Z][^\s/>]*/.exec(html.slice(nameStart, nameStart + 64));
|
|
396
|
+
if (!nameMatch) {
|
|
397
|
+
at = open + 1;
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
const name = nameMatch[0];
|
|
401
|
+
const lower = name.toLowerCase();
|
|
402
|
+
const tag = foreignDepth > 0 ? name : lower;
|
|
403
|
+
const tagEnd = endOfTag(html, nameStart + nameMatch[0].length);
|
|
404
|
+
at = tagEnd + 1;
|
|
405
|
+
if (closing) {
|
|
406
|
+
const match = stack.findLastIndex((entry) => entry.tag.toLowerCase() === lower);
|
|
407
|
+
if (match < 0) continue;
|
|
408
|
+
for (const popped of stack.splice(match)) {
|
|
409
|
+
if (popped.tag.toLowerCase() === "template") templateDepth--;
|
|
410
|
+
if (FOREIGN_ROOTS.has(popped.tag.toLowerCase())) foreignDepth--;
|
|
411
|
+
}
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
const selfClosing = foreignDepth > 0 && html[tagEnd - 1] === "/";
|
|
415
|
+
const parent = stack.length ? stack[stack.length - 1].index : 0;
|
|
416
|
+
let index = parent;
|
|
417
|
+
if (templateDepth === 0) {
|
|
418
|
+
index = elements.push({
|
|
419
|
+
tag,
|
|
420
|
+
parent,
|
|
421
|
+
child: childCounts[parent]++
|
|
422
|
+
}) - 1;
|
|
423
|
+
childCounts.push(0);
|
|
424
|
+
nameEnds.push(nameStart + name.length);
|
|
425
|
+
}
|
|
426
|
+
if (VOID_TAGS.has(lower) || selfClosing) continue;
|
|
427
|
+
if (RAW_TEXT_TAGS.has(lower)) {
|
|
428
|
+
const close = (lowerHtml ??= html.toLowerCase()).indexOf(`</${lower}`, at);
|
|
429
|
+
at = close < 0 ? html.length : endOfTag(html, close + 2 + lower.length) + 1;
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (lower === "template") templateDepth++;
|
|
433
|
+
if (FOREIGN_ROOTS.has(lower)) foreignDepth++;
|
|
434
|
+
stack.push({
|
|
435
|
+
tag,
|
|
436
|
+
index
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
return {
|
|
440
|
+
elements,
|
|
441
|
+
childCounts,
|
|
442
|
+
commentElementIndexes,
|
|
443
|
+
nameEnds
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
function endOfTag(html, from) {
|
|
447
|
+
let quote = "";
|
|
448
|
+
for (let at = from; at < html.length; at++) {
|
|
449
|
+
const char = html[at];
|
|
450
|
+
if (quote) {
|
|
451
|
+
if (char === quote) quote = "";
|
|
452
|
+
} else if (char === "\"" || char === "'") quote = char;
|
|
453
|
+
else if (char === ">") return at;
|
|
454
|
+
}
|
|
455
|
+
return html.length - 1;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* The attribute value for a container whose inner html is `containerHtml`, or
|
|
459
|
+
* undefined when the html holds fewer elements than the locators name.
|
|
460
|
+
* One entry per located element and each of its ancestors, so every entry is
|
|
461
|
+
* one step from its parent; the format is documented on PROTOCOL_LOCATOR_PATHS_DIGITS.
|
|
462
|
+
*/
|
|
463
|
+
function servedLocatorPaths(containerHtml, locators) {
|
|
464
|
+
if (locators.length === 0) return void 0;
|
|
465
|
+
const { elements, childCounts } = servedElementTree(containerHtml);
|
|
466
|
+
const chain = /* @__PURE__ */ new Set();
|
|
467
|
+
for (const { index } of locators) {
|
|
468
|
+
if (index >= elements.length) return void 0;
|
|
469
|
+
for (let at = index; at > 0 && !chain.has(at); at = elements[at].parent) chain.add(at);
|
|
470
|
+
}
|
|
471
|
+
if (chain.size === 0) return void 0;
|
|
472
|
+
const tags = [];
|
|
473
|
+
const parents = [];
|
|
474
|
+
const stack = [0];
|
|
475
|
+
let entries = "";
|
|
476
|
+
let previous = 0;
|
|
477
|
+
for (const index of [...chain].sort((left, right) => left - right)) {
|
|
478
|
+
const { tag, parent, child } = elements[index];
|
|
479
|
+
let up = 0;
|
|
480
|
+
while (stack[stack.length - 1] !== parent) {
|
|
481
|
+
stack.pop();
|
|
482
|
+
up++;
|
|
483
|
+
}
|
|
484
|
+
if (!tags.includes(tag)) tags.push(tag);
|
|
485
|
+
if (!parents.includes(parent)) parents.push(parent);
|
|
486
|
+
entries += pathNumber(up) + pathNumber(index - previous) + pathNumber(child) + pathNumber(tags.indexOf(tag));
|
|
487
|
+
stack.push(index);
|
|
488
|
+
previous = index;
|
|
489
|
+
}
|
|
490
|
+
return `${elements.length}${tags.join(",")}|${entries}|${parents.map((parent) => pathNumber(childCounts[parent])).join("")}`;
|
|
491
|
+
}
|
|
492
|
+
function pathNumber(value) {
|
|
493
|
+
let digits = "";
|
|
494
|
+
for (; value >= 32; value = Math.floor(value / 32)) digits += PROTOCOL_LOCATOR_PATHS_DIGITS[32 + value % 32];
|
|
495
|
+
return digits + PROTOCOL_LOCATOR_PATHS_DIGITS[value];
|
|
496
|
+
}
|
|
497
|
+
//#endregion
|
|
325
498
|
//#region ../web/src/render-to-string.ts
|
|
499
|
+
const MARKLESS_COMPONENT_PART_BRAND = "marklessComponentPart";
|
|
326
500
|
async function assemblePrerenderPageParts(component, output, options) {
|
|
327
501
|
const { state, view } = await prepareSsrResumeRecords(output);
|
|
328
502
|
const browserTriggers = hasBrowserTriggers(view, state);
|
|
329
503
|
const resumeModuleUrl = options.prerenderWakeModuleUrl ?? options.resumeModuleUrl ?? artifactPrerenderWakeModuleUrl(component) ?? artifactResumeModuleUrl(component);
|
|
330
|
-
const modulePreloads = (typeof options.modulePreloads === "function" ? options.modulePreloads(output.html) : options.modulePreloads) ?? (browserTriggers ? artifactModulePreloads(component) : void 0);
|
|
504
|
+
const modulePreloads = (typeof options.modulePreloads === "function" ? options.modulePreloads(output.html, browserTriggers && resumeModuleUrl !== void 0) : options.modulePreloads) ?? (browserTriggers ? artifactModulePreloads(component) : void 0);
|
|
331
505
|
const eventNames = browserEventNames(view);
|
|
332
506
|
const selfWake = hasUnsettledAsyncBoundaryRunner(view, state);
|
|
333
507
|
const boot = artifactPrerenderBoot(component);
|
|
334
508
|
const settle = options.armEmission && selfWake ? boot?.settle : void 0;
|
|
335
|
-
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) : "";
|
|
509
|
+
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) : "";
|
|
336
510
|
return {
|
|
337
511
|
head: [
|
|
338
512
|
renderStorageSeedScript(artifactStorageSeeds(component), options.nonce),
|
|
339
513
|
renderHeadInjections(artifactHeadInjections(component), options.nonce),
|
|
340
514
|
renderModulePreloadLinks(modulePreloads, options.nonce)
|
|
341
515
|
].filter(Boolean).join(""),
|
|
342
|
-
container: [
|
|
343
|
-
`<div${renderContainerAttributes(options.containerId)}>`,
|
|
516
|
+
container: renderContainer(options.containerId, [
|
|
344
517
|
output.html,
|
|
345
|
-
options.armEmission
|
|
346
|
-
resumerScript
|
|
347
|
-
|
|
348
|
-
].filter(Boolean).join("")
|
|
518
|
+
options.armEmission,
|
|
519
|
+
resumerScript
|
|
520
|
+
], resumerScript ? view.locators : [])
|
|
349
521
|
};
|
|
350
522
|
}
|
|
351
523
|
async function renderSsrOutput(component, props, renderContext) {
|
|
352
|
-
|
|
353
|
-
|
|
524
|
+
assertPageRenderable(component);
|
|
525
|
+
globalThis.__marklessRosterResume ??= () => import("./roster-resume-CpphsFl_.js");
|
|
526
|
+
const context = marklessSsrRosterPositionContext(renderContext);
|
|
527
|
+
if (typeof component === "function") return marklessSsrRosterCounted(context, await marklessSsrDeferredCounted(context, await component(props, context)));
|
|
528
|
+
if (component && typeof component.renderSsr === "function") return marklessSsrRosterCounted(context, await marklessSsrDeferredCounted(context, await component.renderSsr(props, context)));
|
|
354
529
|
throw new TypeError("renderToString(App) requires a compiled TSRX artifact.");
|
|
355
530
|
}
|
|
531
|
+
/**
|
|
532
|
+
* The count-spending expressions this render handed over unevaluated. They are
|
|
533
|
+
* answered first: the placeholder resolver that runs after them only has plain
|
|
534
|
+
* count reads left to replace.
|
|
535
|
+
*/
|
|
536
|
+
async function marklessSsrDeferredCounted(renderContext, surface) {
|
|
537
|
+
const seeds = renderContext?.sharedSeeds;
|
|
538
|
+
const deferred = marklessRosterPositions(seeds)?.deferred;
|
|
539
|
+
if (!deferred || deferred.length === 0) return surface;
|
|
540
|
+
const roster = await globalThis.__marklessRosterResume?.();
|
|
541
|
+
if (!roster) throw new Error("MARKLESS_ROSTER_COUNT_UNRESOLVED");
|
|
542
|
+
return roster.marklessResolveDeferredCounts(surface, deferred);
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Refuses a bare component part used AS A PAGE. `renderSsrOutput` is the one
|
|
546
|
+
* place a surface becomes a served page - composition reaches a part through
|
|
547
|
+
* `marklessSsrComponentPart` and never comes here - so the refusal costs
|
|
548
|
+
* composition nothing while a part-as-page can no longer be served inert.
|
|
549
|
+
*/
|
|
550
|
+
function assertPageRenderable(component) {
|
|
551
|
+
const partName = componentPartName(component);
|
|
552
|
+
if (partName === void 0) return;
|
|
553
|
+
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.`);
|
|
554
|
+
}
|
|
555
|
+
function componentPartName(component) {
|
|
556
|
+
if (typeof component !== "object" || component === null) return void 0;
|
|
557
|
+
const name = component[MARKLESS_COMPONENT_PART_BRAND];
|
|
558
|
+
return typeof name === "string" ? name : void 0;
|
|
559
|
+
}
|
|
356
560
|
function artifactResumeModuleUrl(component) {
|
|
357
561
|
return typeof component === "object" ? component.resumeModuleUrl : void 0;
|
|
358
562
|
}
|
|
@@ -371,18 +575,37 @@ function artifactHeadInjections(component) {
|
|
|
371
575
|
function artifactStorageSeeds(component) {
|
|
372
576
|
return typeof component === "object" ? component.storageSeeds : void 0;
|
|
373
577
|
}
|
|
578
|
+
function artifactInlineResumerSources(component) {
|
|
579
|
+
return typeof component === "object" ? component.inlineResumerSources : void 0;
|
|
580
|
+
}
|
|
374
581
|
function renderHeadInjections(injections, nonce) {
|
|
375
582
|
if (!injections?.length) return "";
|
|
376
583
|
return injections.filter((injection) => injection.location === "head").map((injection) => renderHeadInjection(injection, nonce)).join("");
|
|
377
584
|
}
|
|
378
585
|
function renderStorageSeedScript(seeds, nonce) {
|
|
379
586
|
if (!seeds?.length) return "";
|
|
380
|
-
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) => [
|
|
587
|
+
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) => [
|
|
381
588
|
seed.slotKey,
|
|
382
589
|
seed.driverKey,
|
|
383
590
|
storageAttributeName(seed.driverKey),
|
|
384
|
-
seed.fallback
|
|
385
|
-
|
|
591
|
+
seed.fallback,
|
|
592
|
+
storageCookieName(seed.driverKey)
|
|
593
|
+
])))}){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>`;
|
|
594
|
+
}
|
|
595
|
+
function storageWakeSource(state, resumeModuleUrl) {
|
|
596
|
+
const rendered = (state.storage ?? []).flatMap((record) => {
|
|
597
|
+
const value = renderedCellValue(state.cells.find((cell) => cell.graphNodeId === record.graphNodeId));
|
|
598
|
+
return value === void 0 ? [] : [[storageSlotEntryKeyFromGraphNodeId(record.graphNodeId), value]];
|
|
599
|
+
});
|
|
600
|
+
if (rendered.length === 0) return "";
|
|
601
|
+
return createInlineResumerStorageWakeSource(resumeModuleUrl, STORAGE_SLOT_SYMBOL_KEY, escapeScriptJson(JSON.stringify(rendered)));
|
|
602
|
+
}
|
|
603
|
+
function renderedCellValue(cell) {
|
|
604
|
+
if (typeof cell?.directValue === "string") return cell.directValue;
|
|
605
|
+
const value = cell?.value;
|
|
606
|
+
if (typeof value === "string") return value;
|
|
607
|
+
const root = value?.root;
|
|
608
|
+
return typeof root === "string" ? root : void 0;
|
|
386
609
|
}
|
|
387
610
|
function renderHeadInjection(injection, nonce) {
|
|
388
611
|
const attributes = { ...injection.attributes };
|
|
@@ -411,7 +634,7 @@ function renderModulePreloadLinks(preloads, nonce) {
|
|
|
411
634
|
return links.join("");
|
|
412
635
|
}
|
|
413
636
|
function hasBrowserTriggers(view, state) {
|
|
414
|
-
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);
|
|
637
|
+
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);
|
|
415
638
|
}
|
|
416
639
|
function hasUnsettledAsyncBoundaryRunner(view, state) {
|
|
417
640
|
const runners = { ...view.asyncRunners };
|
|
@@ -437,25 +660,55 @@ function boundaryArmEventNames(boundary) {
|
|
|
437
660
|
if (!armRecords || Array.isArray(armRecords)) return [];
|
|
438
661
|
return [...(armRecords.events ?? []).filter(protocolEventDispatchesMarkless).map((event) => event.eventName), ...(armRecords.keyedRepeats ?? []).flatMap((repeat) => repeat.rowEvents.map((event) => event.eventName))];
|
|
439
662
|
}
|
|
663
|
+
function branchServedArmEventNames(branch) {
|
|
664
|
+
const armRecords = branch.servedArmRecords;
|
|
665
|
+
if (!armRecords) return [];
|
|
666
|
+
return [...armRecords.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName), ...(armRecords.keyedRepeats ?? []).flatMap((repeat) => repeat.rowEvents.map((event) => event.eventName))];
|
|
667
|
+
}
|
|
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);
|
|
671
|
+
}
|
|
672
|
+
function deferredTriggerSource(view) {
|
|
673
|
+
const visible = eventHostIndexes(view, PROTOCOL_VISIBLE_EVENT_NAME);
|
|
674
|
+
const idle = eventHostIndexes(view, PROTOCOL_IDLE_EVENT_NAME$1);
|
|
675
|
+
const nested = deferredEventNames({
|
|
676
|
+
...view,
|
|
677
|
+
events: []
|
|
678
|
+
});
|
|
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) : "");
|
|
682
|
+
}
|
|
440
683
|
function browserEventNames(view) {
|
|
441
|
-
return
|
|
684
|
+
return deferredEventNames(view).filter((eventName) => eventName !== PROTOCOL_VISIBLE_EVENT_NAME);
|
|
685
|
+
}
|
|
686
|
+
function deferredEventNames(view) {
|
|
687
|
+
return [.../* @__PURE__ */ new Set([
|
|
442
688
|
...view.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName),
|
|
443
689
|
...(view.keyedRepeats ?? []).flatMap((repeat) => repeat.rowEvents.map((event) => event.eventName)),
|
|
444
|
-
...(view.branches ?? []).flatMap((branch) => (branch.armRecords ?? []).flatMap((arm) => arm.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName))),
|
|
690
|
+
...(view.branches ?? []).flatMap((branch) => [...(branch.armRecords ?? []).flatMap((arm) => arm.events.filter(protocolEventDispatchesMarkless).map((event) => event.eventName)), ...branchServedArmEventNames(branch)]),
|
|
445
691
|
...view.asyncBoundaries.flatMap(boundaryArmEventNames)
|
|
446
|
-
])]
|
|
447
|
-
}
|
|
448
|
-
function
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
692
|
+
])];
|
|
693
|
+
}
|
|
694
|
+
function renderContainer(containerId, parts, locators) {
|
|
695
|
+
const inner = parts.filter(Boolean).join("");
|
|
696
|
+
const paths = servedLocatorPaths(inner, locators);
|
|
697
|
+
const id = containerId ? `="${escapeAttribute(containerId)}"` : "";
|
|
698
|
+
const located = paths ? ` ${PROTOCOL_LOCATOR_PATHS_ATTRIBUTE}="${paths}"` : "";
|
|
699
|
+
return `${CONTAINER_OPEN}${id}${located}>${inner}${CONTAINER_CLOSE}`;
|
|
700
|
+
}
|
|
701
|
+
const CONTAINER_OPEN = `<div ${CONTAINER_ATTRIBUTE}`;
|
|
702
|
+
const CONTAINER_CLOSE = "</div>";
|
|
703
|
+
function renderInlineResumerScript(source, nonce, resumeModuleUrl, selfWake, settleModuleUrl, appendSelfWakeSource = true, overlayPrimer = false, appendedSource = "", deferFactory) {
|
|
452
704
|
const nonceAttribute = nonce ? ` nonce="${escapeAttribute(nonce)}"` : "";
|
|
453
705
|
const resumeModuleAttribute = resumeModuleUrl ? ` data-markless-resume-module="${escapeAttribute(resumeModuleUrl)}"` : "";
|
|
454
706
|
const settleModuleAttribute = settleModuleUrl ? ` data-markless-settle-module="${escapeAttribute(settleModuleUrl)}"` : "";
|
|
455
707
|
const selfWakeAttribute = selfWake ? " data-markless-self-wake" : "";
|
|
456
708
|
const selfWakeSource = selfWake && appendSelfWakeSource ? createInlineResumerSelfWakeSource(resumeModuleUrl) : "";
|
|
457
709
|
const overlayPrimerSource = overlayPrimer ? createInlineResumerOverlayPrimerSource(resumeModuleUrl) : "";
|
|
458
|
-
|
|
710
|
+
const [first, ...rest] = (source + selfWakeSource + overlayPrimerSource + appendedSource).split(inlineDeferSource());
|
|
711
|
+
return `<script data-async-resumer${nonceAttribute}${resumeModuleAttribute}${settleModuleAttribute}${selfWakeAttribute}>${escapeInlineScript(rest.length ? `${first}${inlineDeferSource(deferFactory)}${rest.join("globalThis.__mDefer")}` : first)}<\/script>`;
|
|
459
712
|
}
|
|
460
713
|
function escapeAttribute(value) {
|
|
461
714
|
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
@@ -485,7 +738,8 @@ async function emitPrerenderedPage(input) {
|
|
|
485
738
|
const html = await readFile(htmlFile, "utf8");
|
|
486
739
|
const placeholder = "<div id=\"app\"></div>";
|
|
487
740
|
if (!html.includes(placeholder)) throw new Error("MARKLESS_PRERENDER_CONTAINER_MISSING: expected exact #app build placeholder");
|
|
488
|
-
|
|
741
|
+
const withHead = page.head ? html.replace("</head>", `${page.head}</head>`) : html;
|
|
742
|
+
await writeFile(htmlFile, withHead.replace(placeholder, page.container));
|
|
489
743
|
}
|
|
490
744
|
const SENTINEL_OPEN = "";
|
|
491
745
|
const SENTINEL_CLOSE = "";
|
|
@@ -969,6 +1223,101 @@ async function withBuiltPrerenderPage(input, read) {
|
|
|
969
1223
|
}
|
|
970
1224
|
}
|
|
971
1225
|
//#endregion
|
|
1226
|
+
//#region src/build/deferred-runtime.ts
|
|
1227
|
+
/**
|
|
1228
|
+
* Deferred packs for runtime no compiled demand names: each such dynamic-import target, plus what
|
|
1229
|
+
* only such targets reach. Modules reached from the same targets share one pack, so each target
|
|
1230
|
+
* stays its own chunk. A target other code imports statically still gets a pack: that importer
|
|
1231
|
+
* loads it through its static edge, while no preload plan follows a dynamic edge into it.
|
|
1232
|
+
*/
|
|
1233
|
+
function deferredRuntimePacks(input) {
|
|
1234
|
+
const packs = /* @__PURE__ */ new Map();
|
|
1235
|
+
if (input.undemanded.size === 0) return packs;
|
|
1236
|
+
const undemanded = withUndemandedReExportDoors(input.modules, input.undemanded);
|
|
1237
|
+
const reach = (roots, skipUndemanded) => {
|
|
1238
|
+
const reached = /* @__PURE__ */ new Set();
|
|
1239
|
+
const pending = [...roots];
|
|
1240
|
+
while (pending.length) {
|
|
1241
|
+
const id = pending.pop();
|
|
1242
|
+
if (reached.has(id)) continue;
|
|
1243
|
+
reached.add(id);
|
|
1244
|
+
const module = input.modules.get(id);
|
|
1245
|
+
if (!module) continue;
|
|
1246
|
+
pending.push(...module.dependencies);
|
|
1247
|
+
for (const target of module.dynamicDependencies) if (!skipUndemanded || !undemanded.has(target)) pending.push(target);
|
|
1248
|
+
}
|
|
1249
|
+
return reached;
|
|
1250
|
+
};
|
|
1251
|
+
const lazy = reach(undemanded, false);
|
|
1252
|
+
const kept = reach([...input.modules.keys()].filter((id) => !lazy.has(id)), true);
|
|
1253
|
+
const dynamicTargets = /* @__PURE__ */ new Set();
|
|
1254
|
+
const behindUndemanded = /* @__PURE__ */ new Set();
|
|
1255
|
+
for (const [id, module] of input.modules) {
|
|
1256
|
+
for (const target of module.dynamicDependencies) dynamicTargets.add(target);
|
|
1257
|
+
if (undemanded.has(id)) for (const dependency of module.dependencies) behindUndemanded.add(dependency);
|
|
1258
|
+
}
|
|
1259
|
+
const reachedBy = /* @__PURE__ */ new Map();
|
|
1260
|
+
for (const target of [...undemanded].sort()) {
|
|
1261
|
+
if (behindUndemanded.has(target) && !dynamicTargets.has(target)) continue;
|
|
1262
|
+
const label = runtimeModuleIdFromOrigin(target.split("?")[0]) ?? "runtime";
|
|
1263
|
+
for (const id of reach([target], false)) {
|
|
1264
|
+
if (!input.modules.has(id) || kept.has(id) && !undemanded.has(id)) continue;
|
|
1265
|
+
const labels = reachedBy.get(id) ?? [];
|
|
1266
|
+
if (!labels.includes(label)) labels.push(label);
|
|
1267
|
+
reachedBy.set(id, labels);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
for (const [id, labels] of reachedBy) packs.set(id, `${MARKLESS_DEFERRED_PACK}-${labels.join("+").replace(/[^\w+-]/g, "-")}`);
|
|
1271
|
+
return packs;
|
|
1272
|
+
}
|
|
1273
|
+
function deferredRuntimePlugin(demandMaps) {
|
|
1274
|
+
let packs = /* @__PURE__ */ new Map();
|
|
1275
|
+
return {
|
|
1276
|
+
name: "markless:deferred-runtime",
|
|
1277
|
+
options(input) {
|
|
1278
|
+
return input.preserveEntrySignatures === false ? null : {
|
|
1279
|
+
...input,
|
|
1280
|
+
preserveEntrySignatures: "allow-extension"
|
|
1281
|
+
};
|
|
1282
|
+
},
|
|
1283
|
+
buildEnd(error) {
|
|
1284
|
+
packs = /* @__PURE__ */ new Map();
|
|
1285
|
+
if (error) return;
|
|
1286
|
+
const modules = /* @__PURE__ */ new Map();
|
|
1287
|
+
for (const id of this.getModuleIds()) {
|
|
1288
|
+
const info = this.getModuleInfo(id);
|
|
1289
|
+
if (!info || "isExternal" in info && info.isExternal) continue;
|
|
1290
|
+
modules.set(id, {
|
|
1291
|
+
dependencies: info.importedIds,
|
|
1292
|
+
dynamicDependencies: info.dynamicallyImportedIds,
|
|
1293
|
+
reExportsOnly: isReExportDoor(info)
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
packs = deferredRuntimePacks({
|
|
1297
|
+
modules,
|
|
1298
|
+
undemanded: undemandedRuntimeModules({
|
|
1299
|
+
demandMaps: demandMaps(),
|
|
1300
|
+
moduleIds: modules.keys()
|
|
1301
|
+
})
|
|
1302
|
+
});
|
|
1303
|
+
},
|
|
1304
|
+
outputOptions(output) {
|
|
1305
|
+
if (typeof output.codeSplitting !== "object") return null;
|
|
1306
|
+
return {
|
|
1307
|
+
...output,
|
|
1308
|
+
codeSplitting: {
|
|
1309
|
+
...output.codeSplitting,
|
|
1310
|
+
groups: [{
|
|
1311
|
+
name: (id) => packs.get(id) ?? null,
|
|
1312
|
+
priority: 1e3,
|
|
1313
|
+
includeDependenciesRecursively: false
|
|
1314
|
+
}, ...output.codeSplitting.groups ?? []]
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
//#endregion
|
|
972
1321
|
//#region src/vite/dev-tags.ts
|
|
973
1322
|
function createDevTags() {
|
|
974
1323
|
const tags = [];
|
|
@@ -1003,6 +1352,8 @@ function createDevErrorClientAsset(viteClientUrl) {
|
|
|
1003
1352
|
const hot = createHotContext(${JSON.stringify(MARKLESS_DEV_ERROR_CLIENT_ID)});
|
|
1004
1353
|
const ERROR_EVENT = ${JSON.stringify(MARKLESS_DEV_ERROR_EVENT)};
|
|
1005
1354
|
const CLEAR_EVENT = ${JSON.stringify(MARKLESS_DEV_ERROR_CLEAR_EVENT)};
|
|
1355
|
+
const RELOADS_EVENT = ${JSON.stringify(MARKLESS_DEV_RELOADS_EVENT)};
|
|
1356
|
+
const RELOADS_ATTRIBUTE = ${JSON.stringify(MARKLESS_DEV_RELOADS_ATTRIBUTE)};
|
|
1006
1357
|
const ELEMENT = 'markless-dev-error-overlay';
|
|
1007
1358
|
const SUPPRESSION = 'data-markless-vite-overlay-suppression';
|
|
1008
1359
|
const OPEN_IN_EDITOR = ${JSON.stringify(`${base}/__open-in-editor`)};
|
|
@@ -1076,11 +1427,13 @@ hot.on(CLEAR_EVENT, ({ id }) => { if (currentPayload?.id === id) reset(); });
|
|
|
1076
1427
|
hot.on('vite:beforeFullReload', reset);
|
|
1077
1428
|
addEventListener('keydown', (event) => { if (event.key === 'Escape') document.querySelector(ELEMENT)?.remove(); });
|
|
1078
1429
|
if (window.__MARKLESS_DEV_ERROR__) show(window.__MARKLESS_DEV_ERROR__);
|
|
1430
|
+
const servedAfter = document.querySelector('script[' + RELOADS_ATTRIBUTE + ']')?.getAttribute(RELOADS_ATTRIBUTE);
|
|
1431
|
+
if (servedAfter != null) hot.send(RELOADS_EVENT, { reloads: Number(servedAfter) });
|
|
1079
1432
|
`;
|
|
1080
1433
|
}
|
|
1081
1434
|
//#endregion
|
|
1082
1435
|
//#region src/vite/environment.ts
|
|
1083
|
-
const UNMANAGED_VITE_ENVIRONMENTS = new Set(["nitro"]);
|
|
1436
|
+
const UNMANAGED_VITE_ENVIRONMENTS = /* @__PURE__ */ new Set(["nitro"]);
|
|
1084
1437
|
function viteEnvironmentName(environment, options = {}) {
|
|
1085
1438
|
if (environment === "client") return options.clientEnvironment ?? "client";
|
|
1086
1439
|
if (environment === "server") return options.serverEnvironment ?? "ssr";
|
|
@@ -1106,6 +1459,19 @@ function isUnmanagedViteEnvironment(environment) {
|
|
|
1106
1459
|
function transformMarklessRequest(server, url, environment, options) {
|
|
1107
1460
|
return server.environments[viteEnvironmentName(environment, options)]?.transformRequest(url);
|
|
1108
1461
|
}
|
|
1462
|
+
const serverModuleRunners = /* @__PURE__ */ new WeakMap();
|
|
1463
|
+
function serverModuleRunner(server, environmentName) {
|
|
1464
|
+
const environment = server.environments[environmentName];
|
|
1465
|
+
if (!environment || !isRunnableDevEnvironment(environment)) throw new Error(`MARKLESS_DEV_MODULE_RUNNER_UNAVAILABLE: ${environmentName}`);
|
|
1466
|
+
const byName = serverModuleRunners.get(server) ?? /* @__PURE__ */ new Map();
|
|
1467
|
+
serverModuleRunners.set(server, byName);
|
|
1468
|
+
const existing = byName.get(environmentName);
|
|
1469
|
+
if (existing) return existing;
|
|
1470
|
+
const runner = createServerModuleRunner(environment);
|
|
1471
|
+
byName.set(environmentName, runner);
|
|
1472
|
+
server.httpServer?.once("close", () => void runner.close());
|
|
1473
|
+
return runner;
|
|
1474
|
+
}
|
|
1109
1475
|
function hasInProcessModuleRunner(environment) {
|
|
1110
1476
|
return !!environment && isRunnableDevEnvironment(environment);
|
|
1111
1477
|
}
|
|
@@ -1127,6 +1493,13 @@ function createViteHmr(options) {
|
|
|
1127
1493
|
let recheckingInvalidSources = false;
|
|
1128
1494
|
const preflightByFile = /* @__PURE__ */ new Map();
|
|
1129
1495
|
const unreportedInvalidations = /* @__PURE__ */ new Map();
|
|
1496
|
+
let editReloads = 0;
|
|
1497
|
+
let lastReloadedEdit;
|
|
1498
|
+
function countEditReload(edit) {
|
|
1499
|
+
if (edit === lastReloadedEdit) return;
|
|
1500
|
+
lastReloadedEdit = edit;
|
|
1501
|
+
editReloads += 1;
|
|
1502
|
+
}
|
|
1130
1503
|
let hotUpdatePasses = 0;
|
|
1131
1504
|
let hotUpdateCycle;
|
|
1132
1505
|
function beginHotUpdatePass() {
|
|
@@ -1250,7 +1623,10 @@ function createViteHmr(options) {
|
|
|
1250
1623
|
sendClear(id);
|
|
1251
1624
|
recovered = true;
|
|
1252
1625
|
}
|
|
1253
|
-
if (recovered)
|
|
1626
|
+
if (recovered) {
|
|
1627
|
+
countEditReload(`recovered\0${Date.now()}`);
|
|
1628
|
+
server?.environments?.[options.clientEnvironment]?.hot?.send?.({ type: "full-reload" });
|
|
1629
|
+
}
|
|
1254
1630
|
} finally {
|
|
1255
1631
|
recheckingInvalidSources = false;
|
|
1256
1632
|
stopInvalidSourceRecheckIfIdle();
|
|
@@ -1275,7 +1651,15 @@ function createViteHmr(options) {
|
|
|
1275
1651
|
installServerRenderBarrier(nextServer);
|
|
1276
1652
|
nextServer.httpServer?.once("close", cleanup);
|
|
1277
1653
|
nextServer.watcher?.once?.("close", cleanup);
|
|
1278
|
-
if (options.enabled)
|
|
1654
|
+
if (options.enabled) {
|
|
1655
|
+
installFetchViteClient(nextServer, options, async () => {
|
|
1656
|
+
await settledHotUpdate();
|
|
1657
|
+
return editReloads;
|
|
1658
|
+
});
|
|
1659
|
+
nextServer.environments?.[options.clientEnvironment]?.hot?.on?.(MARKLESS_DEV_RELOADS_EVENT, (data, client) => {
|
|
1660
|
+
if (data?.reloads !== editReloads) client.send({ type: "full-reload" });
|
|
1661
|
+
});
|
|
1662
|
+
}
|
|
1279
1663
|
},
|
|
1280
1664
|
transformIndexHtml() {},
|
|
1281
1665
|
resolveId(id) {
|
|
@@ -1304,6 +1688,17 @@ function createViteHmr(options) {
|
|
|
1304
1688
|
}
|
|
1305
1689
|
}
|
|
1306
1690
|
};
|
|
1691
|
+
function loadedOrInvalid(environments, file) {
|
|
1692
|
+
const path = parsePath(file).pathname;
|
|
1693
|
+
if (invalidSources.has(path)) return true;
|
|
1694
|
+
let answered = false;
|
|
1695
|
+
for (const environment of environments) {
|
|
1696
|
+
if (typeof environment.moduleGraph?.getModulesByFile !== "function") continue;
|
|
1697
|
+
answered = true;
|
|
1698
|
+
if (environment.moduleGraph.getModulesByFile(path)?.size) return true;
|
|
1699
|
+
}
|
|
1700
|
+
return !answered;
|
|
1701
|
+
}
|
|
1307
1702
|
async function runHotUpdate(environment, ctx) {
|
|
1308
1703
|
if (!environment) return;
|
|
1309
1704
|
const env = marklessEnvironment(environment);
|
|
@@ -1320,11 +1715,14 @@ function createViteHmr(options) {
|
|
|
1320
1715
|
reloadModuleRunner();
|
|
1321
1716
|
return [];
|
|
1322
1717
|
}
|
|
1323
|
-
const
|
|
1718
|
+
const modules = new Set(ctx.modules ?? []);
|
|
1719
|
+
if (ctx.file) for (const target of targets.keys()) for (const module of target.moduleGraph?.getModulesByFile?.(ctx.file) ?? []) modules.add(module);
|
|
1720
|
+
if (modules.size === 0 && ctx.file && !loadedOrInvalid(targets.keys(), ctx.file)) return [];
|
|
1721
|
+
const files = changedFiles([...modules]);
|
|
1324
1722
|
const root = server?.config?.root;
|
|
1325
1723
|
if (ctx.file && SOURCE_FILE_EXTENSION.test(ctx.file)) {
|
|
1326
1724
|
const prefix = root && `${root}/`;
|
|
1327
|
-
files.
|
|
1725
|
+
files.set(parsePath(ctx.file).pathname, prefix && ctx.file.startsWith(prefix) ? `/${ctx.file.slice(prefix.length)}` : ctx.file);
|
|
1328
1726
|
}
|
|
1329
1727
|
if (!files.size) return;
|
|
1330
1728
|
let sendMessages = true;
|
|
@@ -1360,8 +1758,8 @@ function createViteHmr(options) {
|
|
|
1360
1758
|
const invalidationEnvironments = [...targets.keys()];
|
|
1361
1759
|
const invalidationScopes = generatedModuleScopes(targets);
|
|
1362
1760
|
const invalidatedGeneratedIds = /* @__PURE__ */ new Set();
|
|
1363
|
-
for (const
|
|
1364
|
-
const candidates = editedSource !== void 0 && ctx.file ? [ctx.file] : hmrCandidates(
|
|
1761
|
+
for (const [sourceId] of files) {
|
|
1762
|
+
const candidates = editedSource !== void 0 && ctx.file ? [ctx.file] : hmrCandidates(sourceId, ctx.file && SOURCE_FILE_EXTENSION.test(ctx.file) ? ctx.file : void 0);
|
|
1365
1763
|
for (const candidate of candidates) for (const scope of invalidationScopes) {
|
|
1366
1764
|
const invalidatedIds = await options.invalidateGeneratedModules?.(candidate, scope, candidate === ctx.file ? editedSource : void 0);
|
|
1367
1765
|
for (const id of invalidatedIds ?? []) {
|
|
@@ -1383,6 +1781,7 @@ function createViteHmr(options) {
|
|
|
1383
1781
|
recordUnreportedInvalidation(targetEnvironment, invalidated);
|
|
1384
1782
|
}
|
|
1385
1783
|
reloadModuleRunner();
|
|
1784
|
+
countEditReload(`${ctx.file}\0${ctx.timestamp}`);
|
|
1386
1785
|
hot.send({
|
|
1387
1786
|
type: "full-reload",
|
|
1388
1787
|
path: firstChangedFile(files),
|
|
@@ -1398,16 +1797,17 @@ async function fetchedModuleNode(environment, id) {
|
|
|
1398
1797
|
function hasErrorCode(error, code) {
|
|
1399
1798
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
1400
1799
|
}
|
|
1401
|
-
function installFetchViteClient(server, options) {
|
|
1800
|
+
function installFetchViteClient(server, options, servedAfterReloads) {
|
|
1402
1801
|
for (const environment of Object.values(server.environments)) {
|
|
1403
1802
|
const fetchEnv = fetchableDevEnvironment(environment);
|
|
1404
1803
|
if (!fetchEnv) continue;
|
|
1405
1804
|
const dispatchFetch = fetchEnv.dispatchFetch.bind(fetchEnv);
|
|
1406
1805
|
fetchEnv.dispatchFetch = async (request) => {
|
|
1806
|
+
const reloads = await servedAfterReloads();
|
|
1407
1807
|
const response = await dispatchFetch(request);
|
|
1408
1808
|
if (!response.headers.get("content-type")?.includes("text/html")) return response;
|
|
1409
1809
|
const html = await response.text();
|
|
1410
|
-
const nextHtml = injectDevClients(html, options.base);
|
|
1810
|
+
const nextHtml = injectDevClients(html, options.base, reloads);
|
|
1411
1811
|
const headers = new Headers(response.headers);
|
|
1412
1812
|
if (nextHtml !== html) headers.delete("content-length");
|
|
1413
1813
|
return new Response(nextHtml, {
|
|
@@ -1418,9 +1818,9 @@ function installFetchViteClient(server, options) {
|
|
|
1418
1818
|
};
|
|
1419
1819
|
}
|
|
1420
1820
|
}
|
|
1421
|
-
function injectDevClients(html, base) {
|
|
1821
|
+
function injectDevClients(html, base, reloads) {
|
|
1422
1822
|
if (!html) return html;
|
|
1423
|
-
const tags = [...html.includes("/@vite/client") ? [] : [`<script type="module" src="${joinURL(base, "/@vite/client")}"><\/script>`], ...html.includes("virtual:markless:dev-error-client") ? [] : [`<script type="module" src="${joinURL(base, `/@id/__x00__${MARKLESS_DEV_ERROR_CLIENT_ID}`)}"><\/script>`]].join("");
|
|
1823
|
+
const tags = [...html.includes("/@vite/client") ? [] : [`<script type="module" src="${joinURL(base, "/@vite/client")}"><\/script>`], ...html.includes("virtual:markless:dev-error-client") ? [] : [`<script type="module" src="${joinURL(base, `/@id/__x00__${MARKLESS_DEV_ERROR_CLIENT_ID}`)}"${reloads === void 0 ? "" : ` ${MARKLESS_DEV_RELOADS_ATTRIBUTE}="${reloads}"`}><\/script>`]].join("");
|
|
1424
1824
|
if (!tags) return html;
|
|
1425
1825
|
if (html.includes("</head>")) return html.replace("</head>", `${tags}</head>`);
|
|
1426
1826
|
if (html.includes("<head>")) return html.replace("<head>", `<head>${tags}`);
|
|
@@ -1431,7 +1831,7 @@ function clientHot(server, options, environment) {
|
|
|
1431
1831
|
return environment.hot;
|
|
1432
1832
|
}
|
|
1433
1833
|
function invalidationTargets(server, options, environment, env) {
|
|
1434
|
-
const targets = new Map([[environment, env]]);
|
|
1834
|
+
const targets = /* @__PURE__ */ new Map([[environment, env]]);
|
|
1435
1835
|
const clientEnvironment = server?.environments?.[options.clientEnvironment];
|
|
1436
1836
|
if (clientEnvironment) targets.set(clientEnvironment, "client");
|
|
1437
1837
|
for (const [name, candidate] of Object.entries(server?.environments ?? {})) {
|
|
@@ -1454,10 +1854,10 @@ function moduleRunnerHots(targets, clientChannel) {
|
|
|
1454
1854
|
return [...hots];
|
|
1455
1855
|
}
|
|
1456
1856
|
function changedFiles(modules) {
|
|
1457
|
-
const files = /* @__PURE__ */ new
|
|
1857
|
+
const files = /* @__PURE__ */ new Map();
|
|
1458
1858
|
for (const module of modules) for (const item of [module, ...module.importers ?? []]) {
|
|
1459
1859
|
const url = sourceUrl(item);
|
|
1460
|
-
if (url) files.
|
|
1860
|
+
if (url) files.set(parsePath(item.id ?? item.file ?? url).pathname, url);
|
|
1461
1861
|
}
|
|
1462
1862
|
return files;
|
|
1463
1863
|
}
|
|
@@ -1467,12 +1867,12 @@ function sourceUrl(module) {
|
|
|
1467
1867
|
return null;
|
|
1468
1868
|
}
|
|
1469
1869
|
function hmrCandidates(file, absoluteFile) {
|
|
1470
|
-
const candidates = new Set([file]);
|
|
1870
|
+
const candidates = /* @__PURE__ */ new Set([file]);
|
|
1471
1871
|
if (absoluteFile) candidates.add(absoluteFile);
|
|
1472
1872
|
return candidates;
|
|
1473
1873
|
}
|
|
1474
1874
|
function firstChangedFile(files) {
|
|
1475
|
-
for (const file of files) return file;
|
|
1875
|
+
for (const file of files.values()) return file;
|
|
1476
1876
|
}
|
|
1477
1877
|
//#endregion
|
|
1478
1878
|
//#region src/vite/dev-prerender.ts
|
|
@@ -1533,7 +1933,8 @@ function createDevPrerender(input) {
|
|
|
1533
1933
|
} catch (error) {
|
|
1534
1934
|
const environment = server?.environments[input.serverEnvironment];
|
|
1535
1935
|
input.reportError(environment, error);
|
|
1536
|
-
|
|
1936
|
+
const payload = normalizeMarklessDevError(error, { id: input.entry });
|
|
1937
|
+
return injectDevClients(renderMarklessDevErrorDocument(payload, { base: input.base }), input.base);
|
|
1537
1938
|
}
|
|
1538
1939
|
},
|
|
1539
1940
|
configureServer(nextServer) {
|
|
@@ -1544,6 +1945,49 @@ function createDevPrerender(input) {
|
|
|
1544
1945
|
};
|
|
1545
1946
|
}
|
|
1546
1947
|
//#endregion
|
|
1948
|
+
//#region src/vite/dev-server-externals.ts
|
|
1949
|
+
function withDevServerExternals(context) {
|
|
1950
|
+
const config = context.environment?.config;
|
|
1951
|
+
if (config?.consumer !== "server") return context;
|
|
1952
|
+
const noExternal = config.resolve?.noExternal;
|
|
1953
|
+
const resolve = async (source, importer, options) => {
|
|
1954
|
+
const resolved = await context.resolve(source, importer, options);
|
|
1955
|
+
if (!isBareSpecifier(source) || matchesNoExternal(noExternal, source)) return resolved;
|
|
1956
|
+
const id = typeof resolved === "string" ? resolved : resolved?.id;
|
|
1957
|
+
if (!id || !isBuiltDependency(pathname(String(id)))) return resolved;
|
|
1958
|
+
return {
|
|
1959
|
+
...typeof resolved === "object" ? resolved : {},
|
|
1960
|
+
id: String(id),
|
|
1961
|
+
external: true
|
|
1962
|
+
};
|
|
1963
|
+
};
|
|
1964
|
+
return new Proxy(context, { get(target, property) {
|
|
1965
|
+
if (property === "resolve") return resolve;
|
|
1966
|
+
const value = Reflect.get(target, property, target);
|
|
1967
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
1968
|
+
} });
|
|
1969
|
+
}
|
|
1970
|
+
function isBareSpecifier(source) {
|
|
1971
|
+
return !source.startsWith(".") && !isAbsolute(source) && !source.startsWith("\0") && !source.startsWith("virtual:");
|
|
1972
|
+
}
|
|
1973
|
+
function isBuiltDependency(id) {
|
|
1974
|
+
return id.includes("/node_modules/") && /\.[cm]?js$/.test(id);
|
|
1975
|
+
}
|
|
1976
|
+
function matchesNoExternal(noExternal, source) {
|
|
1977
|
+
if (noExternal === true) return true;
|
|
1978
|
+
if (noExternal === void 0) return false;
|
|
1979
|
+
return (typeof noExternal === "string" || noExternal instanceof RegExp ? [noExternal] : noExternal).some((pattern) => typeof pattern === "string" ? source === pattern || source.startsWith(`${pattern}/`) : pattern.test(source));
|
|
1980
|
+
}
|
|
1981
|
+
//#endregion
|
|
1982
|
+
//#region src/vite/dev-runtime-imports.ts
|
|
1983
|
+
function installDevRuntimeImportResolution(server, clientEnvironment) {
|
|
1984
|
+
for (const [name, environment] of Object.entries(server.environments ?? {})) {
|
|
1985
|
+
if (name === clientEnvironment || typeof environment.fetchModule !== "function") continue;
|
|
1986
|
+
const fetchModule = environment.fetchModule.bind(environment);
|
|
1987
|
+
environment.fetchModule = (id, importer, options) => fetchModule(marklessRuntimeSpecifierId(id) ?? id, importer, options);
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
//#endregion
|
|
1547
1991
|
//#region src/vite/index.ts
|
|
1548
1992
|
const MARKLESS_SKIP_DUPLICATE_BUILDS = Symbol("markless-skip-duplicate-builds");
|
|
1549
1993
|
const TSRX_INPUT_FILE = /\.tsrx(?:[?#].*)?$/;
|
|
@@ -1552,7 +1996,12 @@ function markless(options = {}) {
|
|
|
1552
1996
|
const bundleGraphAdders = /* @__PURE__ */ new Set();
|
|
1553
1997
|
const transformedTsrxSources = /* @__PURE__ */ new Map();
|
|
1554
1998
|
const prerenderRecordsBySource = /* @__PURE__ */ new Map();
|
|
1555
|
-
const
|
|
1999
|
+
const { experimentalNativePacking: _deprecatedPacking, ...rest } = options;
|
|
2000
|
+
const rolldownOptions = {
|
|
2001
|
+
...rest,
|
|
2002
|
+
packing: nativePackingEnabled(options),
|
|
2003
|
+
chunkImportMap: options.experimentalNativePacking === true
|
|
2004
|
+
};
|
|
1556
2005
|
const prerender = process.env.MARKLESS_PRERENDER === "1";
|
|
1557
2006
|
const explicitPrerenderWake = process.env.MARKLESS_PRERENDER_WAKE;
|
|
1558
2007
|
rolldownOptions.prerender = false;
|
|
@@ -1609,12 +2058,17 @@ function markless(options = {}) {
|
|
|
1609
2058
|
__MARKLESS_DEV_ENABLED__: devDefine
|
|
1610
2059
|
};
|
|
1611
2060
|
configDefaults(config, options, rolldownOptions);
|
|
2061
|
+
if (devEnabled) {
|
|
2062
|
+
includeOptimizedDeps(config, [RESUME_ENTRY_SPECIFIER, STORAGE_FREE_RESUME_ENTRY_SPECIFIER]);
|
|
2063
|
+
excludeSourceShippedDeps(config);
|
|
2064
|
+
}
|
|
1612
2065
|
if (prerender || stagePrerenderWake) {
|
|
1613
2066
|
prerenderEntry = ssrTsrxInput(config, options);
|
|
1614
2067
|
rolldownOptions.prerender = prerender && prerenderEntry !== null;
|
|
1615
2068
|
}
|
|
1616
2069
|
},
|
|
1617
2070
|
configResolved(resolvedConfig) {
|
|
2071
|
+
if (options.experimentalNativePacking !== void 0) resolvedConfig.logger.warn(DEPRECATED_NATIVE_PACKING_WARNING);
|
|
1618
2072
|
resolvedRoot = resolvedConfig.root;
|
|
1619
2073
|
clientOutDir = resolvedConfig.build?.outDir ?? "dist";
|
|
1620
2074
|
const serve = resolvedConfig.command === "serve";
|
|
@@ -1694,9 +2148,10 @@ function markless(options = {}) {
|
|
|
1694
2148
|
}
|
|
1695
2149
|
},
|
|
1696
2150
|
configureServer(server) {
|
|
1697
|
-
server.config.logger?.info(
|
|
2151
|
+
server.config.logger?.info(`markless diagnostics available - window.__MARKLESS_DEBUG__ records containers, lifecycles, and event routing; ${DEBUGGING_PLAYBOOK_HINT}.`);
|
|
1698
2152
|
rolldownOptions.devServer = {
|
|
1699
2153
|
transformRequest: (url, environment) => transformMarklessRequest(server, url, environment, options),
|
|
2154
|
+
importModule: (source) => serverModuleRunner(server, viteEnvironmentName("server", options)).import(source),
|
|
1700
2155
|
invalidateModule: (id, environment) => {
|
|
1701
2156
|
const target = server.environments[viteEnvironmentName(environment, options)];
|
|
1702
2157
|
const module = target?.moduleGraph?.getModuleById?.(id);
|
|
@@ -1706,6 +2161,7 @@ function markless(options = {}) {
|
|
|
1706
2161
|
}
|
|
1707
2162
|
};
|
|
1708
2163
|
hmr.configureServer(server);
|
|
2164
|
+
installDevRuntimeImportResolution(server, viteEnvironmentName("client", options));
|
|
1709
2165
|
devPrerender?.configureServer(server);
|
|
1710
2166
|
},
|
|
1711
2167
|
transformIndexHtml(html) {
|
|
@@ -1737,7 +2193,8 @@ function markless(options = {}) {
|
|
|
1737
2193
|
transform: { async handler(code, id, transformOptions) {
|
|
1738
2194
|
if (rolldownOptions.dev === true && TSRX_INPUT_FILE.test(id)) transformedTsrxSources.set(parsePath(id).pathname, code);
|
|
1739
2195
|
try {
|
|
1740
|
-
|
|
2196
|
+
const context = rolldownOptions.dev === true ? withDevServerExternals(this) : this;
|
|
2197
|
+
return await runHook(basePlugin.transform, context, code, id, transformOptions);
|
|
1741
2198
|
} catch (error) {
|
|
1742
2199
|
if (rolldownOptions.dev === true && TSRX_INPUT_FILE.test(id)) {
|
|
1743
2200
|
const environment = this.environment;
|
|
@@ -1751,7 +2208,52 @@ function markless(options = {}) {
|
|
|
1751
2208
|
return hmr.hotUpdate(this.environment, ctx);
|
|
1752
2209
|
}
|
|
1753
2210
|
};
|
|
1754
|
-
return [
|
|
2211
|
+
return [
|
|
2212
|
+
marklessPlugin,
|
|
2213
|
+
{
|
|
2214
|
+
name: "markless:shared-render-data-reach",
|
|
2215
|
+
enforce: "pre",
|
|
2216
|
+
resolveId: {
|
|
2217
|
+
filter: { id: /[?&]markless-reached-from=/ },
|
|
2218
|
+
async handler(source, importer) {
|
|
2219
|
+
const shared = sharedReachedRenderDataRequest(source);
|
|
2220
|
+
return shared ? await this.resolve(shared, importer, { skipSelf: true }) : null;
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
},
|
|
2224
|
+
{
|
|
2225
|
+
name: "markless:init-facade-imports",
|
|
2226
|
+
apply: "build",
|
|
2227
|
+
enforce: "pre",
|
|
2228
|
+
applyToEnvironment(environment) {
|
|
2229
|
+
return environment.config.consumer === "client";
|
|
2230
|
+
},
|
|
2231
|
+
generateBundle: {
|
|
2232
|
+
order: "post",
|
|
2233
|
+
async handler(_options, bundle) {
|
|
2234
|
+
await prefetchChunkParses(Object.values(bundle).filter((output) => output.type === "chunk" && output.code.includes("import(")));
|
|
2235
|
+
collapseInitFacadeImports(bundle);
|
|
2236
|
+
unwrapAsyncImportWrappers(bundle);
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
},
|
|
2240
|
+
...nativePackingEnabled(options) ? nativePackingPlugins(() => resolvedRoot, () => basePlugin.api.runtimeDemandMaps(), () => basePlugin.api.runtimeDemandSources()).map((plugin) => ({
|
|
2241
|
+
...plugin,
|
|
2242
|
+
apply: "build",
|
|
2243
|
+
enforce: "post",
|
|
2244
|
+
sharedDuringBuild: true,
|
|
2245
|
+
applyToEnvironment(environment) {
|
|
2246
|
+
return environment.config.consumer === "client";
|
|
2247
|
+
}
|
|
2248
|
+
})) : [{
|
|
2249
|
+
...deferredRuntimePlugin(() => basePlugin.api.runtimeDemandMaps()),
|
|
2250
|
+
apply: "build",
|
|
2251
|
+
enforce: "post",
|
|
2252
|
+
applyToEnvironment(environment) {
|
|
2253
|
+
return environment.config.consumer === "client";
|
|
2254
|
+
}
|
|
2255
|
+
}]
|
|
2256
|
+
];
|
|
1755
2257
|
}
|
|
1756
2258
|
async function buildMarklessEnvironments(builder, options) {
|
|
1757
2259
|
const environments = buildEnvironments(builder, options);
|