@markless/bundler 0.1.1 → 0.2.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.
@@ -1,8 +1,11 @@
1
- import { S as planModulePreloads, _ as requalifyExecutionLogModuleHook, a as resumeVirtualModuleId, b as outputDefaults, c as symbolVirtualModuleId, d as MARKLESS_EXECUTION_SIZES, f as createExecutionSizesAsset, g as normalizeExecutionLogMode, h as injectExecutionLogModuleHook, i as payloadModule, l as symbolVirtualModuleSourceFile, m as executionLogVirtualModuleSource, n as emitResumeModule, o as rewriteSymbolModuleExport, p as executionLogActivationInjection, r as emitSourceModule, s as scopedSymbolExportName, t as MARKLESS_VIRTUAL_PREFIX, u as MARKLESS_EXECUTION_LOG_MODULE_ID, v as MARKLESS_BUILD_PREFIX, y as MARKLESS_BUNDLE_GRAPH } from "./source-module-CSRzW4Ny.js";
1
+ import { MarklessCompileError, createCompileErrorPayload } from "./dev-error.js";
2
+ import { C as planModulePreloads, _ as normalizeExecutionLogMode, a as payloadModule, b as MARKLESS_BUNDLE_GRAPH, c as scopedSymbolExportName, d as MARKLESS_EXECUTION_LOG_MODULE_ID, f as MARKLESS_EXECUTION_SIZES, g as injectExecutionLogModuleHook, h as executionLogVirtualModuleSource, i as encodedSymbolSource, l as symbolVirtualModuleId, m as executionLogActivationInjection, n as emitResumeModule, o as resumeVirtualModuleId, p as createExecutionSizesAsset, r as emitSourceModule, s as rewriteSymbolModuleExport, t as MARKLESS_VIRTUAL_PREFIX, u as symbolVirtualModuleSourceFile, v as requalifyExecutionLogModuleHook, x as outputDefaults, y as MARKLESS_BUILD_PREFIX } from "./source-module-C8W2THUI.js";
2
3
  import { joinURL, parsePath, withLeadingSlash, withQuery, withoutLeadingSlash } from "ufo";
3
4
  import { dirname, isAbsolute, join, normalize, relative, resolve } from "pathe";
4
5
  import { defDGraph } from "@thi.ng/dgraph";
5
- import { compileTsrxModule, emitSymbolResolverModule, parseJavaScriptModule } from "@markless/compiler";
6
+ import { collectTsrxModuleDiagnostics, compileTsrxModule, emitSymbolResolverModule, parseJavaScriptModule } from "@markless/compiler";
7
+ import { createStorageSeedMetadataFromGraphNodeId } from "@markless/serializer";
8
+ import { createInlineResumerDebugRegistrationSource, createInlineResumerSource } from "@markless/web/inline/resumer";
6
9
  //#region src/build/bundle-graph.ts
7
10
  const SLOW_BUNDLE_TOTAL = 300 * 1024 / 8 * .5;
8
11
  const SMALL_BUNDLE_TOTAL = 1e3;
@@ -887,7 +890,7 @@ function rewriteDynamicImportSpecifiers(chunk, rewrites) {
887
890
  return {
888
891
  code: chunk.code.replace(LOCAL_DYNAMIC_IMPORT_HELPER_RE, (match, quote, specifier, parameter, helperName, exportQuote, exportName) => {
889
892
  if (!isLocalSpecifier(specifier)) return match;
890
- const importedFileName = resolveChunkSpecifier(chunk.fileName, specifier);
893
+ const importedFileName = resolveChunkSpecifier$1(chunk.fileName, specifier);
891
894
  const rewrite = rewrites.get(importedFileName);
892
895
  if (!rewrite) return match;
893
896
  if (!rewrite.target.exports.includes(exportName)) return match;
@@ -896,7 +899,7 @@ function rewriteDynamicImportSpecifiers(chunk, rewrites) {
896
899
  return `import(${quote}${nextSpecifier}${quote}).then(${parameter}=>${helperName}(${parameter},${exportQuote}${exportName}${exportQuote}))`;
897
900
  }).replace(LOCAL_DYNAMIC_IMPORT_RE, (match, quote, specifier, parameter, exportName) => {
898
901
  if (!isLocalSpecifier(specifier)) return match;
899
- const importedFileName = resolveChunkSpecifier(chunk.fileName, specifier);
902
+ const importedFileName = resolveChunkSpecifier$1(chunk.fileName, specifier);
900
903
  const rewrite = rewrites.get(importedFileName);
901
904
  if (!rewrite) return match;
902
905
  if (rewrite.initExports.length > 0 && (!parameter || !exportName)) return match;
@@ -1058,7 +1061,7 @@ function findBlockEnd(code, open) {
1058
1061
  }
1059
1062
  return -1;
1060
1063
  }
1061
- function resolveChunkSpecifier(importerFileName, specifier) {
1064
+ function resolveChunkSpecifier$1(importerFileName, specifier) {
1062
1065
  return normalize(join(dirname(importerFileName), specifier));
1063
1066
  }
1064
1067
  function relativeChunkSpecifier$1(importerFileName, targetFileName) {
@@ -1169,6 +1172,299 @@ function normalizeVirtualId$2(id) {
1169
1172
  return id.startsWith("\0") ? id.slice(1) : id;
1170
1173
  }
1171
1174
  //#endregion
1175
+ //#region ../web/src/debug-channel.ts
1176
+ function installDebugChannelLayer(root, initialPhase, initiallyActive = true) {
1177
+ const global = globalThis;
1178
+ const previous = global.__MARKLESS_DEBUG__?.version === 1 ? global.__MARKLESS_DEBUG__ : void 0;
1179
+ let priorRoot;
1180
+ try {
1181
+ priorRoot = previous?.explainInteraction(root, "__markless_debug_root__");
1182
+ } catch {}
1183
+ const priorContainer = priorRoot && "containerId" in priorRoot ? previous?.containers.find((entry) => entry.id === priorRoot.containerId) : void 0;
1184
+ const seed = `${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
1185
+ const id = priorContainer?.id ?? `container:${seed}`;
1186
+ const rootKey = priorContainer?.root.key ?? `root:${seed}`;
1187
+ const rootRef = new WeakRef(root);
1188
+ const events = /* @__PURE__ */ new WeakMap();
1189
+ const keys = /* @__PURE__ */ new WeakMap();
1190
+ const invalidated = /* @__PURE__ */ new WeakSet();
1191
+ const routerSources = global[Symbol.for("markless.debug.channel.v1.router-sources")] ??= /* @__PURE__ */ new Set();
1192
+ const ownViolations = [];
1193
+ let phase = initialPhase;
1194
+ let lifecycle = initiallyActive ? "active" : "registered";
1195
+ let boundarySnapshots = Object.freeze([]);
1196
+ let nextElement = 1;
1197
+ let nextSequence = (previous?.violations.at(-1)?.sequence ?? 0) + 1;
1198
+ let dropped = 0;
1199
+ let pruned = false;
1200
+ const freeze = (value) => Object.freeze(value);
1201
+ const contains = (element) => {
1202
+ const currentRoot = rootRef.deref();
1203
+ return !!currentRoot && (currentRoot === element || currentRoot.contains?.(element) === true);
1204
+ };
1205
+ const keyFor = (element) => {
1206
+ let key = keys.get(element);
1207
+ if (!key) {
1208
+ key = `${rootKey}:element:${nextElement++}`;
1209
+ keys.set(element, key);
1210
+ }
1211
+ return key;
1212
+ };
1213
+ const eligibleAnchor = (element) => {
1214
+ const anchor = element.closest?.("a[href]");
1215
+ if (!anchor?.hasAttribute("data-markless-router-link") || anchor.hasAttribute("download")) return false;
1216
+ const target = anchor.getAttribute("target");
1217
+ if (target && target !== "_self" || anchor.relList?.contains("external")) return false;
1218
+ try {
1219
+ const base = global.location?.href ?? "http://localhost/";
1220
+ return new URL(anchor.href ?? "", base).origin === new URL(base).origin;
1221
+ } catch {
1222
+ return false;
1223
+ }
1224
+ };
1225
+ const none = (element, eventName, reason) => freeze({
1226
+ kind: "none",
1227
+ eventName,
1228
+ reason,
1229
+ containerId: id,
1230
+ elementKey: keyFor(element)
1231
+ });
1232
+ const explain = (element, eventName) => {
1233
+ if (lifecycle === "disposed" && (contains(element) || keys.has(element))) return none(element, eventName, "container-disposed");
1234
+ if (!contains(element)) try {
1235
+ return previous?.explainInteraction(element, eventName) ?? freeze({
1236
+ kind: "none",
1237
+ eventName,
1238
+ reason: "outside-known-container"
1239
+ });
1240
+ } catch {
1241
+ return freeze({
1242
+ kind: "none",
1243
+ eventName,
1244
+ reason: "outside-known-container"
1245
+ });
1246
+ }
1247
+ if (element.isConnected === false) return none(element, eventName, "element-disconnected");
1248
+ if (eligibleAnchor(element)) {
1249
+ const source = eventName === "navigate" && routerSources.has("navigation-event") ? "navigation-event" : eventName === "click" && routerSources.has("spa-click-listener") ? "spa-click-listener" : eventName === "click" && routerSources.has("ssr-link-bridge") ? "ssr-link-bridge" : void 0;
1250
+ if (source) return freeze({
1251
+ kind: "router-delegation",
1252
+ source,
1253
+ containerId: id,
1254
+ elementKey: keyFor(element),
1255
+ eventName
1256
+ });
1257
+ }
1258
+ const interaction = events.get(element)?.get(eventName);
1259
+ if (interaction) return freeze({ ...interaction });
1260
+ if (invalidated.has(element)) return none(element, eventName, "not-registered");
1261
+ try {
1262
+ const prior = previous?.explainInteraction(element, eventName);
1263
+ if (prior && prior.kind !== "none") return prior;
1264
+ } catch {}
1265
+ return none(element, eventName, "not-registered");
1266
+ };
1267
+ const cloneJson = (value, seen = /* @__PURE__ */ new Set()) => {
1268
+ if (value === null) return null;
1269
+ if (typeof value === "boolean" || typeof value === "string") return value;
1270
+ if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
1271
+ if (!value || typeof value !== "object" || seen.has(value)) return void 0;
1272
+ seen.add(value);
1273
+ if (Array.isArray(value)) {
1274
+ const copy = value.map((entry) => cloneJson(entry, seen));
1275
+ return copy.some((entry) => entry === void 0) ? void 0 : freeze(copy);
1276
+ }
1277
+ if (Object.getPrototypeOf(value) !== Object.prototype) return void 0;
1278
+ const copy = {};
1279
+ for (const [name, entry] of Object.entries(value)) {
1280
+ const cloned = cloneJson(entry, seen);
1281
+ if (cloned === void 0) return void 0;
1282
+ copy[name] = cloned;
1283
+ }
1284
+ return freeze(copy);
1285
+ };
1286
+ const pushViolation = (input) => {
1287
+ const cloned = input.details === void 0 ? void 0 : cloneJson(input.details);
1288
+ const details = cloned && !Array.isArray(cloned) && typeof cloned === "object" ? cloned : void 0;
1289
+ const { details: _details, ...metadata } = input;
1290
+ ownViolations.push(freeze({
1291
+ ...metadata,
1292
+ ...details ? { details } : {},
1293
+ sequence: nextSequence++,
1294
+ timestamp: Date.now()
1295
+ }));
1296
+ if (input.details !== void 0 && !details) ownViolations.push(freeze({
1297
+ code: "MARKLESS_DEBUG_DETAILS_DROPPED",
1298
+ message: "Debug violation details were not JSON-safe and were dropped.",
1299
+ sequence: nextSequence++,
1300
+ timestamp: Date.now()
1301
+ }));
1302
+ while (ownViolations.length > 100) {
1303
+ ownViolations.shift();
1304
+ dropped++;
1305
+ }
1306
+ };
1307
+ const channel = freeze({
1308
+ version: 1,
1309
+ get containers() {
1310
+ const inherited = previous?.containers.filter((entry) => entry.id !== id) ?? [];
1311
+ if (pruned || lifecycle === "disposed") return freeze([...inherited]);
1312
+ const currentRoot = rootRef.deref();
1313
+ const connected = !!currentRoot && currentRoot.isConnected !== false;
1314
+ const snapshot = freeze({
1315
+ id,
1316
+ phase,
1317
+ lifecycle: connected ? lifecycle : "disposed",
1318
+ root: freeze({
1319
+ key: rootKey,
1320
+ connected
1321
+ }),
1322
+ boundaries: freeze([...boundarySnapshots])
1323
+ });
1324
+ if (!connected) pruned = true;
1325
+ return freeze([...inherited, snapshot]);
1326
+ },
1327
+ get violations() {
1328
+ return freeze([...previous?.violations ?? [], ...ownViolations].slice(-100));
1329
+ },
1330
+ violationCapacity: 100,
1331
+ get droppedViolationCount() {
1332
+ return (previous?.droppedViolationCount ?? 0) + dropped;
1333
+ },
1334
+ explainInteraction: explain
1335
+ });
1336
+ Object.defineProperty(global, "__MARKLESS_DEBUG__", {
1337
+ configurable: true,
1338
+ enumerable: false,
1339
+ value: channel,
1340
+ writable: false
1341
+ });
1342
+ return {
1343
+ start(nextPhase, active = true) {
1344
+ phase = nextPhase === "ssr-resume" && phase === "csr" ? "csr" : nextPhase;
1345
+ if (active) lifecycle = "active";
1346
+ return id;
1347
+ },
1348
+ activate: () => void (lifecycle === "disposed" || (lifecycle = "active")),
1349
+ dispose() {
1350
+ lifecycle = "disposed";
1351
+ boundarySnapshots = freeze([]);
1352
+ },
1353
+ invalidate(element) {
1354
+ events.delete(element);
1355
+ invalidated.add(element);
1356
+ },
1357
+ record(element, eventName, input) {
1358
+ if (lifecycle === "disposed") return;
1359
+ let byName = events.get(element);
1360
+ if (!byName) events.set(element, byName = /* @__PURE__ */ new Map());
1361
+ const symbolIds = "symbolIds" in input ? freeze([...input.symbolIds]) : void 0;
1362
+ byName.set(eventName, freeze({
1363
+ ...input,
1364
+ ...symbolIds ? { symbolIds } : {},
1365
+ containerId: id,
1366
+ elementKey: keyFor(element),
1367
+ eventName
1368
+ }));
1369
+ },
1370
+ violation: pushViolation,
1371
+ router: (source) => void routerSources.add(source),
1372
+ boundaries(value) {
1373
+ boundarySnapshots = freeze(value.map((entry) => freeze({ ...entry })));
1374
+ },
1375
+ disposed: () => lifecycle === "disposed"
1376
+ };
1377
+ }
1378
+ function __marklessDebugBootstrapSource() {
1379
+ return `((root,phase,active)=>{const controls=(${installDebugChannelLayer.toString()})(root,phase,active);return Object.freeze({record:(element,eventName,input)=>controls.record(element,eventName,input),router:(source)=>controls.router(source),activate:()=>controls.activate()})})`;
1380
+ }
1381
+ //#endregion
1382
+ //#region src/inline-resumer.ts
1383
+ let oxcToolsPromise;
1384
+ const compiledSources = /* @__PURE__ */ new Map();
1385
+ function loadOxcTools() {
1386
+ oxcToolsPromise ??= import("rolldown/experimental").then(({ minifySync, transformSync }) => ({
1387
+ minifySync,
1388
+ transformSync
1389
+ }));
1390
+ return oxcToolsPromise;
1391
+ }
1392
+ function compileInlineResumerSources(options) {
1393
+ const cacheKey = `${options.debug ? "debug" : "production"}:${options.executionLog}`;
1394
+ let compiled = compiledSources.get(cacheKey);
1395
+ if (!compiled) {
1396
+ compiled = compileInlineResumerSourceVariants(options);
1397
+ compiledSources.set(cacheKey, compiled);
1398
+ }
1399
+ return compiled;
1400
+ }
1401
+ async function compileInlineResumerSourceVariants(options) {
1402
+ const shared = {
1403
+ debug: options.debug,
1404
+ executionLog: options.executionLog
1405
+ };
1406
+ const [event, syncPolicy, graphSyncPolicyOwner, graphSyncPolicyConsumer] = await Promise.all([
1407
+ compileInlineResumerSource({
1408
+ ...shared,
1409
+ graphSyncPolicy: false,
1410
+ sharedGraphPolicy: false,
1411
+ syncPolicy: false
1412
+ }),
1413
+ compileInlineResumerSource({
1414
+ ...shared,
1415
+ graphSyncPolicy: false,
1416
+ sharedGraphPolicy: false,
1417
+ syncPolicy: true
1418
+ }),
1419
+ compileInlineResumerSource({
1420
+ ...shared,
1421
+ graphSyncPolicy: true,
1422
+ sharedGraphPolicy: true,
1423
+ syncPolicy: true
1424
+ }),
1425
+ compileInlineResumerSource({
1426
+ ...shared,
1427
+ graphSyncPolicy: true,
1428
+ sharedGraphPolicy: false,
1429
+ syncPolicy: true
1430
+ })
1431
+ ]);
1432
+ return {
1433
+ ...shared,
1434
+ event,
1435
+ syncPolicy,
1436
+ graphSyncPolicyOwner,
1437
+ graphSyncPolicyConsumer
1438
+ };
1439
+ }
1440
+ async function compileInlineResumerSource(options) {
1441
+ const source = createInlineResumerSource({
1442
+ ...options,
1443
+ ...options.debug ? {
1444
+ debugBootstrapSource: __marklessDebugBootstrapSource(),
1445
+ debugRegistrationSource: createInlineResumerDebugRegistrationSource()
1446
+ } : {}
1447
+ });
1448
+ const { minifySync, transformSync } = await loadOxcTools();
1449
+ const transformed = transformSync("markless-inline-resumer.js", source, {
1450
+ lang: "js",
1451
+ sourceType: "script",
1452
+ target: "es2020"
1453
+ });
1454
+ assertOxcResult("transform", transformed.errors);
1455
+ const minified = minifySync("markless-inline-resumer.js", transformed.code, {
1456
+ compress: true,
1457
+ mangle: { toplevel: true },
1458
+ module: false
1459
+ });
1460
+ assertOxcResult("minify", minified.errors);
1461
+ return minified.code.trim();
1462
+ }
1463
+ function assertOxcResult(phase, errors) {
1464
+ if (errors.length === 0) return;
1465
+ throw new Error(`MARKLESS_INLINE_RESUMER_${phase.toUpperCase()}_FAILED:\n${errors.map((error) => error.message).join("\n")}`);
1466
+ }
1467
+ //#endregion
1172
1468
  //#region src/transform.ts
1173
1469
  let oxcTransformSyncPromise;
1174
1470
  function loadOxcTransformSync() {
@@ -1191,29 +1487,32 @@ async function transformTsrxModule(input) {
1191
1487
  const payloadId = `${MARKLESS_VIRTUAL_PREFIX}payload:${encodedFilename}`;
1192
1488
  const resolverId = `${MARKLESS_VIRTUAL_PREFIX}resolver:${encodedFilename}`;
1193
1489
  const resumeId = resumeVirtualModuleId(input.filename);
1194
- const compiled = await compileTsrxModule({
1195
- filename: input.filename,
1196
- source: input.source,
1197
- buildId: input.buildId,
1198
- resolverId,
1199
- symbols: []
1200
- });
1490
+ const { compiled, blockingDiagnostics } = await compileWithBlockingDiagnostics(input, resolverId);
1491
+ throwIfBlocked(input, blockingDiagnostics);
1201
1492
  const symbolRows = compiled.symbolModules.modules.map((module) => ({
1202
1493
  id: module.symbolId,
1203
1494
  chunk: symbolVirtualModuleId(input.filename, module.symbolId),
1204
1495
  exportName: scopedSymbolExportName(input.filename, module.exportName)
1205
1496
  }));
1206
- const resolverSource = emitSymbolResolverModule({
1497
+ const importedBoundRows = compiled.boundSymbolResolver.rows.map((row) => row.loaderSymbolId ? {
1498
+ ...row,
1499
+ baseSymbolId: row.loaderSymbolId
1500
+ } : row);
1501
+ const resolverSource = adaptImportedCaptureResolver(emitSymbolResolverModule({
1207
1502
  buildId: input.buildId,
1208
- symbols: symbolRows
1209
- });
1503
+ symbols: uniqueSymbolsById([...input.symbols ?? [], ...symbolRows]),
1504
+ boundSymbols: importedBoundRows
1505
+ }), importedBoundRows.some((row) => row.loaderSymbolId !== void 0));
1210
1506
  const symbolRoutes = compiled.semanticGraph.componentEdges.flatMap((edge, index) => edge.importSource ? [{
1211
1507
  prefix: `c${index}:`,
1212
- importSource: edge.importSource
1508
+ importSource: edge.importSource,
1509
+ componentEdgeId: edge.id
1213
1510
  }] : []);
1214
1511
  const executionLogModuleHookMode = input.executionLogModuleHooks === false ? "never" : input.executionLog;
1215
1512
  const manifest = {
1216
1513
  source: input.filename,
1514
+ captureMetadata: compiled.captureAnalysis,
1515
+ symbolRoutes,
1217
1516
  payload: { virtualModuleId: payloadId },
1218
1517
  resolver: { virtualModuleId: resolverId },
1219
1518
  symbols: compiled.symbolModules.modules.map((module, index) => ({
@@ -1255,7 +1554,8 @@ async function transformTsrxModule(input) {
1255
1554
  payloadView: containerScopedResumeView(compiled.payloadScripts.view),
1256
1555
  runtimeDemandMap: compiled.runtimeDemandMap,
1257
1556
  executionLog: input.executionLog,
1258
- needsFullResume: needsFullResume(compiled.protocolView, compiled.runtimeDemandMap),
1557
+ needsFullResume: needsFullResume(compiled.protocolState, compiled.protocolView, compiled.runtimeDemandMap),
1558
+ hasBoundSymbols: compiled.boundSymbolResolver.rows.length > 0,
1259
1559
  symbols: symbolRows,
1260
1560
  symbolRoutes
1261
1561
  })
@@ -1268,17 +1568,37 @@ async function transformTsrxModule(input) {
1268
1568
  source: injectExecutionLogModuleHook(await stripEmittedTypes(rewriteSymbolModuleExport(module.source, module.exportName, symbolRows[index].exportName)), `symbol:${module.symbolId}`, executionLogModuleHookMode)
1269
1569
  })))
1270
1570
  ];
1571
+ const styleImport = styleId ? `import ${JSON.stringify(styleId)};\n` : "";
1572
+ const inlineResumerSources = (input.environment ?? "lib") === "client" ? void 0 : await compileInlineResumerSources({
1573
+ debug: input.inlineResumerDebug === true,
1574
+ executionLog: input.executionLog ?? "never"
1575
+ });
1576
+ const headInjections = [...input.headInjections ?? [], ...styleId && input.styleModuleUrl ? [{
1577
+ tag: "link",
1578
+ location: "head",
1579
+ attributes: {
1580
+ rel: "stylesheet",
1581
+ href: input.styleModuleUrl(styleId)
1582
+ }
1583
+ }] : []];
1584
+ const storageSeeds = compiled.payloadArena.state.storage.map((storage) => {
1585
+ const binding = compiled.semanticGraph.graphBindings.find((candidate) => candidate.id === storage.graphNodeId);
1586
+ if (typeof binding?.initialValue !== "string") throw new Error(`MARKLESS_STORAGE_SEED_FALLBACK_MISSING: ${storage.graphNodeId} has no static string fallback.`);
1587
+ return createStorageSeedMetadataFromGraphNodeId(storage.graphNodeId, storage.key, binding.initialValue);
1588
+ });
1271
1589
  return {
1272
- code: (styleId ? `import ${JSON.stringify(styleId)};\n` : "") + await stripEmittedTypes(emitSourceModule({
1590
+ code: styleImport + await stripEmittedTypes(emitSourceModule({
1273
1591
  filename: input.filename,
1274
1592
  payloadId,
1275
1593
  resolverId,
1276
1594
  environment: input.environment ?? "lib",
1277
1595
  clientOutput: input.clientOutput ?? "full",
1278
1596
  executionLog: input.executionLog,
1279
- headInjections: input.headInjections,
1597
+ headInjections: headInjections.length > 0 ? headInjections : void 0,
1598
+ storageSeeds: storageSeeds.length > 0 ? storageSeeds : void 0,
1599
+ inlineResumerSources,
1280
1600
  devResumeReexport: input.devResumeReexport === true,
1281
- needsFullResume: needsFullResume(compiled.protocolView, compiled.runtimeDemandMap),
1601
+ needsFullResume: needsFullResume(compiled.protocolState, compiled.protocolView, compiled.runtimeDemandMap),
1282
1602
  resumeModuleUrl: input.resumeModuleUrl,
1283
1603
  publicRenderModuleSource: compiled.publicRenderModule.moduleSource,
1284
1604
  publicRenderRootExportName: compiled.publicRenderModule.rootExportName,
@@ -1286,6 +1606,7 @@ async function transformTsrxModule(input) {
1286
1606
  publicRenderCsrExportName: compiled.publicRenderModule.csrExportName,
1287
1607
  publicSsrModuleSource: compiled.publicRenderModule.ssrModuleSource,
1288
1608
  publicRenderSsrExportName: compiled.publicRenderModule.ssrExportName,
1609
+ hasBoundSymbols: compiled.boundSymbolResolver.rows.length > 0,
1289
1610
  symbols: symbolRows,
1290
1611
  symbolRoutes
1291
1612
  })),
@@ -1294,6 +1615,89 @@ async function transformTsrxModule(input) {
1294
1615
  manifest
1295
1616
  };
1296
1617
  }
1618
+ async function preflightTsrxModuleDiagnostics(input) {
1619
+ const { blockingDiagnostics } = await compileWithBlockingDiagnostics(input, `${MARKLESS_VIRTUAL_PREFIX}resolver:${encodeURIComponent(input.filename)}`);
1620
+ throwIfBlocked(input, blockingDiagnostics);
1621
+ }
1622
+ async function compileWithBlockingDiagnostics(input, resolverId) {
1623
+ const compiled = await compileTsrxModule({
1624
+ filename: input.filename,
1625
+ source: input.source,
1626
+ buildId: input.buildId,
1627
+ resolverId,
1628
+ symbols: input.symbols ?? []
1629
+ });
1630
+ return {
1631
+ compiled,
1632
+ blockingDiagnostics: collectTsrxModuleDiagnostics(compiled).filter((diagnostic) => diagnostic.severity === "error")
1633
+ };
1634
+ }
1635
+ function throwIfBlocked(input, blockingDiagnostics) {
1636
+ if (blockingDiagnostics.length === 0) return;
1637
+ const details = formatBlockedCompileError(input, blockingDiagnostics);
1638
+ throw new MarklessCompileError(createCompileErrorPayload({
1639
+ filename: input.filename,
1640
+ source: input.source,
1641
+ diagnostics: blockingDiagnostics,
1642
+ details
1643
+ }));
1644
+ }
1645
+ function formatBlockedCompileError(input, diagnostics) {
1646
+ return [`MARKLESS_COMPILE_BLOCKED: ${input.filename} has ${diagnostics.length} compiler error(s).`, ...diagnostics.map((diagnostic) => {
1647
+ const position = diagnostic.primarySpan ? formatSourcePosition(input.source, diagnostic.primarySpan.start) : void 0;
1648
+ const location = position ? ` (${diagnostic.primarySpan.filename}:${position.line}:${position.column})` : "";
1649
+ return [
1650
+ `${diagnostic.code}: ${diagnostic.message}${location}`,
1651
+ diagnostic.why,
1652
+ diagnostic.suggestions[0]?.message,
1653
+ diagnostic.docsUrl
1654
+ ].filter((line) => Boolean(line)).join("\n");
1655
+ })].join("\n\n");
1656
+ }
1657
+ function formatSourcePosition(source, start) {
1658
+ const sourceBeforeSpan = source.slice(0, start);
1659
+ const lastLineBreak = sourceBeforeSpan.lastIndexOf("\n");
1660
+ return {
1661
+ line: sourceBeforeSpan.split("\n").length,
1662
+ column: sourceBeforeSpan.length - lastLineBreak
1663
+ };
1664
+ }
1665
+ function uniqueSymbolsById(symbols) {
1666
+ return [...new Map(symbols.map((symbol) => [symbol.id, symbol])).values()];
1667
+ }
1668
+ function adaptImportedCaptureResolver(source, hasImportedRows) {
1669
+ if (!hasImportedRows) return source;
1670
+ const original = " return (context) => base({ ...context, capture: createCaptureContext(context, bound) });";
1671
+ const replacement = [
1672
+ " return async (context) => {",
1673
+ " const pendingCallbacks = [];",
1674
+ " const capture = createCaptureContext(context, bound);",
1675
+ " const result = await base({ ...context, graph: createBoundGraph(context, bound, capture, pendingCallbacks), capture });",
1676
+ " await Promise.all(pendingCallbacks);",
1677
+ " return result;",
1678
+ " };"
1679
+ ].join("\n");
1680
+ const helper = [
1681
+ "function createBoundGraph(context, bound, capture, pendingCallbacks) {",
1682
+ " const legacySlots = new Map(bound.captureSlots.flatMap((slot) => slot.legacyGraphRead ? [[JSON.stringify([slot.legacyGraphRead.graphNodeId, slot.legacyGraphRead.path ?? []]), slot]] : []));",
1683
+ " return {",
1684
+ " ...context.graph,",
1685
+ " read(graphNodeId, path = []) {",
1686
+ " const slot = legacySlots.get(JSON.stringify([graphNodeId, path]));",
1687
+ " if (!slot) return context.graph.read(graphNodeId, path);",
1688
+ " if (slot.route.kind === callbackRoute) return (...args) => {",
1689
+ " const pending = context.invokeSymbol(slot.route.callbackSymbolId, { ...context, event: context.event, args });",
1690
+ " pendingCallbacks.push(Promise.resolve(pending));",
1691
+ " return pending;",
1692
+ " };",
1693
+ " return capture.read(slot.slotId);",
1694
+ " },",
1695
+ " };",
1696
+ "}",
1697
+ ""
1698
+ ].join("\n");
1699
+ return source.replace(original, replacement).replace("function createCaptureContext(context, bound) {", `${helper}function createCaptureContext(context, bound) {`);
1700
+ }
1297
1701
  function containerScopedResumeView(view) {
1298
1702
  return {
1299
1703
  ...view,
@@ -1303,7 +1707,8 @@ function containerScopedResumeView(view) {
1303
1707
  }))
1304
1708
  };
1305
1709
  }
1306
- function needsFullResume(view, runtimeDemandMap) {
1710
+ function needsFullResume(state, view, runtimeDemandMap) {
1711
+ if ((state.storage?.length ?? 0) > 0) return true;
1307
1712
  if ((view.branches?.length ?? 0) > 0) return true;
1308
1713
  if ((view.elementHandles?.length ?? 0) > 0) return true;
1309
1714
  if ((view.asyncBoundaries?.length ?? 0) > 0) return true;
@@ -1316,10 +1721,13 @@ function recordKindReplaced(runtimeDemandMap, kind) {
1316
1721
  //#endregion
1317
1722
  //#region src/build/symbol-table.ts
1318
1723
  const SYMBOL_VIRTUAL_PREFIX = `${MARKLESS_VIRTUAL_PREFIX}symbol:`;
1724
+ const PACKED_SYMBOL_VIRTUAL_LIST_RE = /(["'`])((?:virtual:markless:symbol:)[^"'`]+)\1\.split\(\s*(["'`]),\3\s*\)/g;
1319
1725
  const SYMBOL_VIRTUAL_STRING_RE$1 = /(["'`])((?:virtual:markless:symbol:)[^"'`]+)\1/g;
1320
- const SYMBOL_MANIFEST_TUPLE_RE = /(\[1,(?:null|["'`][^"'`]*["'`]),(?:null|["'`][^"'`]*["'`]),)(\[[^\]]*\]),(\[[^\]]*\]),(\{[^}]*\})(\])/g;
1726
+ const STRING_LIST_SOURCE = String.raw`(?:\[[^\]]*\]|["'\x60][^"'\x60]*["'\x60]\.split\(\s*["'\x60][^"'\x60]*["'\x60]\s*\))`;
1727
+ const SYMBOL_MANIFEST_TUPLE_RE = new RegExp(String.raw`(\[1,(?:null|["'\x60][^"'\x60]*["'\x60]),(?:null|["'\x60][^"'\x60]*["'\x60]),)(${STRING_LIST_SOURCE}),(${STRING_LIST_SOURCE}),(\{[^}]*\})(\])`, "g");
1321
1728
  const STRING_LITERAL_RE = /(["'`])([^"'`]*)\1/g;
1322
1729
  const SYMBOL_ROW_RE = /((?:["'`][^"'`]*["'`])\s*:\s*\[)(\d+)(,\s*\d+\])/g;
1730
+ const SYMBOL_ROW_CAPTURE_RE = /(["'`])([^"'`]*)\1\s*:\s*\[(\d+),\s*(\d+)\]/g;
1323
1731
  function rewriteGeneratedSymbolTableUrls(bundle) {
1324
1732
  const chunks = collectChunks(bundle);
1325
1733
  const symbolFiles = collectGeneratedSymbolFiles(chunks);
@@ -1337,6 +1745,56 @@ function rewriteGeneratedSymbolTableUrls(bundle) {
1337
1745
  unresolved: [...unresolved].sort()
1338
1746
  };
1339
1747
  }
1748
+ /**
1749
+ * Checks emitted resolver routes against compiler manifests and Rolldown's
1750
+ * chunk ownership/export metadata. Table source is read only to recover each
1751
+ * claimed file; termination evidence stays structural.
1752
+ */
1753
+ function verifyGeneratedSymbolTableRoutes(bundle, manifests) {
1754
+ const chunks = collectChunks(bundle);
1755
+ const errors = [];
1756
+ let verified = 0;
1757
+ for (const manifest of manifests) {
1758
+ if (manifest.symbols.length === 0) continue;
1759
+ const resolverChunk = findResolverRouteChunk(chunks, manifest.resolver.virtualModuleId, manifest.symbols);
1760
+ const routeChunk = resolverChunk ?? findChunkForVirtualId(chunks, manifest.source);
1761
+ if (!routeChunk) {
1762
+ for (const symbol of manifest.symbols) errors.push({
1763
+ symbolId: symbol.symbolId,
1764
+ claimedChunk: "<missing route chunk>",
1765
+ reason: `neither compiler resolver ${manifest.resolver.virtualModuleId} nor source ${manifest.source} was emitted`
1766
+ });
1767
+ continue;
1768
+ }
1769
+ const table = resolverChunk ? findSymbolTable(routeChunk.code, manifest.symbols) : void 0;
1770
+ for (const symbol of manifest.symbols) {
1771
+ if (!table) {
1772
+ const directRoute = verifyDirectRoute(chunks, routeChunk, symbol);
1773
+ if (directRoute.reason) errors.push({
1774
+ symbolId: symbol.symbolId,
1775
+ claimedChunk: directRoute.claimedChunk,
1776
+ reason: directRoute.reason
1777
+ });
1778
+ else verified++;
1779
+ continue;
1780
+ }
1781
+ const specifier = tableRouteSpecifier(table, symbol, routeChunk.fileName, errors);
1782
+ if (!specifier) continue;
1783
+ const claimedChunk = resolveChunkSpecifier(routeChunk.fileName, specifier);
1784
+ const reason = routeTerminationError(chunks, claimedChunk, symbol);
1785
+ if (reason) errors.push({
1786
+ symbolId: symbol.symbolId,
1787
+ claimedChunk,
1788
+ reason
1789
+ });
1790
+ else verified++;
1791
+ }
1792
+ }
1793
+ return {
1794
+ verified,
1795
+ errors
1796
+ };
1797
+ }
1340
1798
  function collectChunks(bundle) {
1341
1799
  const chunks = /* @__PURE__ */ new Map();
1342
1800
  for (const output of Object.values(bundle)) if (isGeneratedChunk(output)) chunks.set(output.fileName, output);
@@ -1344,9 +1802,135 @@ function collectChunks(bundle) {
1344
1802
  }
1345
1803
  function collectGeneratedSymbolFiles(chunks) {
1346
1804
  const symbolFiles = /* @__PURE__ */ new Map();
1347
- for (const chunk of chunks.values()) for (const id of virtualIds(chunk)) if (id.startsWith(SYMBOL_VIRTUAL_PREFIX)) symbolFiles.set(id, chunk.fileName);
1805
+ for (const chunk of chunks.values()) {
1806
+ const facadeId = chunk.facadeModuleId ? normalizeVirtualId$1(chunk.facadeModuleId) : void 0;
1807
+ if (facadeId?.startsWith(SYMBOL_VIRTUAL_PREFIX)) symbolFiles.set(facadeId, chunk.fileName);
1808
+ }
1809
+ for (const chunk of chunks.values()) for (const id of chunk.moduleIds.map(normalizeVirtualId$1)) if (id.startsWith(SYMBOL_VIRTUAL_PREFIX) && !symbolFiles.has(id)) symbolFiles.set(id, chunk.fileName);
1348
1810
  return symbolFiles;
1349
1811
  }
1812
+ function findSymbolTable(code, symbols) {
1813
+ let bestMatch;
1814
+ let bestScore = -1;
1815
+ for (const match of code.matchAll(SYMBOL_MANIFEST_TUPLE_RE)) {
1816
+ const moduleUrls = parseStringList(match[2]);
1817
+ const exportNames = parseStringList(match[3]);
1818
+ if (!moduleUrls || !exportNames) continue;
1819
+ const rows = /* @__PURE__ */ new Map();
1820
+ for (const row of match[4].matchAll(SYMBOL_ROW_CAPTURE_RE)) rows.set(row[2], [Number(row[3]), Number(row[4])]);
1821
+ if (rows.size === 0) continue;
1822
+ const score = symbols.filter((symbol) => exportNames.includes(symbol.exportName)).length;
1823
+ if (score > bestScore) {
1824
+ bestMatch = {
1825
+ moduleUrls,
1826
+ exportNames,
1827
+ rows
1828
+ };
1829
+ bestScore = score;
1830
+ }
1831
+ }
1832
+ return bestMatch;
1833
+ }
1834
+ function tableRouteSpecifier(table, symbol, resolverFileName, errors) {
1835
+ const row = table.rows.get(symbol.symbolId);
1836
+ if (!row) {
1837
+ errors.push({
1838
+ symbolId: symbol.symbolId,
1839
+ claimedChunk: resolverFileName,
1840
+ reason: "emitted symbol table has no row for this compiler symbol"
1841
+ });
1842
+ return;
1843
+ }
1844
+ const specifier = table.moduleUrls[row[0]];
1845
+ if (!specifier) {
1846
+ errors.push({
1847
+ symbolId: symbol.symbolId,
1848
+ claimedChunk: resolverFileName,
1849
+ reason: `emitted symbol table references missing module URL index ${row[0]}`
1850
+ });
1851
+ return;
1852
+ }
1853
+ const exportName = table.exportNames[row[1]];
1854
+ if (exportName !== symbol.exportName) {
1855
+ errors.push({
1856
+ symbolId: symbol.symbolId,
1857
+ claimedChunk: resolveChunkSpecifier(resolverFileName, specifier),
1858
+ reason: `emitted symbol table claims export ${exportName ?? `<missing index ${row[1]}>`} instead of ${symbol.exportName}`
1859
+ });
1860
+ return;
1861
+ }
1862
+ return specifier;
1863
+ }
1864
+ function verifyDirectRoute(chunks, routeChunk, symbol) {
1865
+ const target = findChunkForVirtualId(chunks, symbol.virtualModuleId);
1866
+ if (!target) return {
1867
+ claimedChunk: "<missing symbol chunk>",
1868
+ reason: `generated symbol module ${symbol.virtualModuleId} was not emitted`
1869
+ };
1870
+ if (!(target.exports ?? []).includes(symbol.exportName)) return {
1871
+ claimedChunk: target.fileName,
1872
+ reason: `claimed chunk does not export ${symbol.exportName}`
1873
+ };
1874
+ if (!dynamicRouteReachesChunk(chunks, routeChunk, target.fileName) && !rewrittenSpecifierRoutesTo(routeChunk, target.fileName)) return {
1875
+ claimedChunk: target.fileName,
1876
+ reason: `source chunk ${routeChunk.fileName} has no emitted dynamic route to the claimed chunk`
1877
+ };
1878
+ return { claimedChunk: target.fileName };
1879
+ }
1880
+ function rewrittenSpecifierRoutesTo(routeChunk, targetFileName) {
1881
+ const specifier = relativeChunkSpecifier(routeChunk.fileName, targetFileName);
1882
+ return routeChunk.code.includes(JSON.stringify(specifier)) || routeChunk.code.includes(`'${specifier}'`) || routeChunk.code.includes(`\`${specifier}\``);
1883
+ }
1884
+ function dynamicRouteReachesChunk(chunks, start, targetFileName) {
1885
+ const pending = [start];
1886
+ const visited = /* @__PURE__ */ new Set();
1887
+ while (pending.length > 0) {
1888
+ const chunk = pending.shift();
1889
+ if (chunk.fileName === targetFileName) return true;
1890
+ if (visited.has(chunk.fileName)) continue;
1891
+ visited.add(chunk.fileName);
1892
+ for (const importedFileName of chunk.dynamicImports ?? []) {
1893
+ const imported = chunks.get(importedFileName);
1894
+ if (imported) pending.push(imported);
1895
+ }
1896
+ }
1897
+ return false;
1898
+ }
1899
+ function routeTerminationError(chunks, claimedChunk, symbol) {
1900
+ const target = chunks.get(claimedChunk);
1901
+ if (!target) return "claimed chunk was not emitted. markless debugging playbook: run pnpm doctor, or read agent/markless.md in the installed @markless/core package";
1902
+ if (!chunkOrReexportChainContainsSymbol(chunks, target, normalizeVirtualId$1(symbol.virtualModuleId), symbol.exportName)) return `claimed chunk does not contain its generated symbol module ${symbol.virtualModuleId} or a live re-export chain to it. markless debugging playbook: run pnpm doctor, or read agent/markless.md in the installed @markless/core package`;
1903
+ if (!(target.exports ?? []).includes(symbol.exportName)) return `claimed chunk does not export ${symbol.exportName}. markless debugging playbook: run pnpm doctor, or read agent/markless.md in the installed @markless/core package`;
1904
+ }
1905
+ function chunkOrReexportChainContainsSymbol(chunks, start, virtualId, exportName) {
1906
+ const pending = [start];
1907
+ const visited = /* @__PURE__ */ new Set();
1908
+ while (pending.length > 0) {
1909
+ const chunk = pending.shift();
1910
+ if (visited.has(chunk.fileName)) continue;
1911
+ visited.add(chunk.fileName);
1912
+ if (virtualIds(chunk).includes(virtualId) && (chunk.exports ?? []).includes(exportName)) return true;
1913
+ if (!(chunk.exports ?? []).includes(exportName)) continue;
1914
+ for (const importedFileName of chunk.imports ?? []) {
1915
+ const imported = chunks.get(importedFileName);
1916
+ if (imported && (imported.exports ?? []).includes(exportName)) pending.push(imported);
1917
+ }
1918
+ }
1919
+ return false;
1920
+ }
1921
+ function findChunkForVirtualId(chunks, virtualId) {
1922
+ const normalized = normalizeVirtualId$1(virtualId);
1923
+ return [...chunks.values()].find((chunk) => !!chunk.facadeModuleId && normalizeVirtualId$1(chunk.facadeModuleId) === normalized) ?? [...chunks.values()].find((chunk) => chunk.moduleIds.map(normalizeVirtualId$1).includes(normalized));
1924
+ }
1925
+ function findResolverRouteChunk(chunks, virtualId, symbols) {
1926
+ const normalized = normalizeVirtualId$1(virtualId);
1927
+ const candidates = [...chunks.values()].filter((chunk) => virtualIds(chunk).includes(normalized));
1928
+ return candidates.find((chunk) => !!findSymbolTable(chunk.code, symbols)) ?? candidates.find((chunk) => chunk.moduleIds.map(normalizeVirtualId$1).includes(normalized)) ?? candidates[0];
1929
+ }
1930
+ function resolveChunkSpecifier(importerFileName, specifier) {
1931
+ if (!specifier.startsWith(".")) return normalize(specifier);
1932
+ return normalize(join(dirname(importerFileName), specifier));
1933
+ }
1350
1934
  function virtualIds(chunk) {
1351
1935
  return [chunk.facadeModuleId ?? void 0, ...chunk.moduleIds].filter((id) => !!id).map(normalizeVirtualId$1);
1352
1936
  }
@@ -1354,7 +1938,16 @@ function rewriteSymbolVirtualStrings(chunk, symbolFiles) {
1354
1938
  let rewritten = 0;
1355
1939
  const unresolved = /* @__PURE__ */ new Set();
1356
1940
  return {
1357
- code: compactSymbolManifestTables(chunk.code.replace(SYMBOL_VIRTUAL_STRING_RE$1, (match, _quote, virtualId) => {
1941
+ code: compactSymbolManifestTables(chunk.code.replace(PACKED_SYMBOL_VIRTUAL_LIST_RE, (match, _quote, packedVirtualIds) => {
1942
+ const virtualIds = packedVirtualIds.split(",");
1943
+ if (virtualIds.length < 2 || virtualIds.some((id) => !id.startsWith(SYMBOL_VIRTUAL_PREFIX))) return match;
1944
+ return JSON.stringify(virtualIds.map((virtualId) => {
1945
+ const fileName = symbolFiles.get(virtualId);
1946
+ if (!fileName) return virtualId;
1947
+ rewritten++;
1948
+ return relativeChunkSpecifier(chunk.fileName, fileName);
1949
+ }));
1950
+ }).replace(SYMBOL_VIRTUAL_STRING_RE$1, (match, _quote, virtualId) => {
1358
1951
  const fileName = symbolFiles.get(virtualId);
1359
1952
  if (!fileName) {
1360
1953
  unresolved.add(virtualId);
@@ -1403,6 +1996,11 @@ function parseStringArray(source) {
1403
1996
  if (source.slice(end).trim() !== "]") return void 0;
1404
1997
  return values;
1405
1998
  }
1999
+ function parseStringList(source) {
2000
+ if (source.startsWith("[")) return parseStringArray(source);
2001
+ const packed = source.match(/^(["'`])([^"'`]*)\1\.split\(\s*(["'`])([^"'`]*)\3\s*\)$/);
2002
+ return packed ? packed[2].split(packed[4]) : void 0;
2003
+ }
1406
2004
  function relativeChunkSpecifier(importerFileName, targetFileName) {
1407
2005
  const value = relative(dirname(importerFileName), targetFileName).replaceAll("\\", "/");
1408
2006
  return value.startsWith(".") ? value : `./${value}`;
@@ -1496,6 +2094,9 @@ function createMarklessRolldownPlugin(input) {
1496
2094
  const internalOptions = input.options ?? {};
1497
2095
  const virtualModules = /* @__PURE__ */ new Map();
1498
2096
  const transformManifests = /* @__PURE__ */ new Map();
2097
+ const importedChildren = /* @__PURE__ */ new Map();
2098
+ const importedChildSources = /* @__PURE__ */ new Set();
2099
+ const emittedClientResolverSources = /* @__PURE__ */ new Set();
1499
2100
  const sourceVirtualModules = /* @__PURE__ */ new Map();
1500
2101
  const clientSymbolEntrySources = /* @__PURE__ */ new Set();
1501
2102
  const executionLogEstimatedSizes = /* @__PURE__ */ new Map();
@@ -1512,8 +2113,16 @@ function createMarklessRolldownPlugin(input) {
1512
2113
  return {
1513
2114
  api: { invalidateGeneratedModules(parent, currentEnvironment) {
1514
2115
  const ids = dev.clear(parent, currentEnvironment);
1515
- for (const id of ids) virtualModules.delete(id);
1516
- return ids.map(resolveVirtualId);
2116
+ const resolvedIds = /* @__PURE__ */ new Set();
2117
+ for (const id of ids) {
2118
+ const type = virtualModules.get(id)?.type;
2119
+ virtualModules.delete(id);
2120
+ const resolvedId = resolveVirtualId(id);
2121
+ resolvedIds.add(resolvedId);
2122
+ if (type === "style") resolvedIds.add(`${resolvedId}?direct`);
2123
+ }
2124
+ if ((currentEnvironment === "client" || currentEnvironment === void 0 && environment === "client") && internalOptions.dev === true && normalizeExecutionLogMode(internalOptions.executionLog) !== "never") resolvedIds.add(resolveVirtualId(MARKLESS_EXECUTION_LOG_MODULE_ID));
2125
+ return [...resolvedIds];
1517
2126
  } },
1518
2127
  name,
1519
2128
  options(input) {
@@ -1528,6 +2137,9 @@ function createMarklessRolldownPlugin(input) {
1528
2137
  clientSymbolEntrySources.clear();
1529
2138
  virtualModules.clear();
1530
2139
  transformManifests.clear();
2140
+ importedChildren.clear();
2141
+ importedChildSources.clear();
2142
+ emittedClientResolverSources.clear();
1531
2143
  sourceVirtualModules.clear();
1532
2144
  executionLogEstimatedSizes.clear();
1533
2145
  dev.reset();
@@ -1554,10 +2166,14 @@ function createMarklessRolldownPlugin(input) {
1554
2166
  id: resolveVirtualId(MARKLESS_EXECUTION_LOG_MODULE_ID),
1555
2167
  moduleSideEffects: true
1556
2168
  };
1557
- if (virtualModules.has(normalized)) return {
1558
- id: resolveVirtualId(normalized),
1559
- moduleSideEffects: true
1560
- };
2169
+ const virtualModule = virtualModules.get(normalized);
2170
+ if (virtualModule) {
2171
+ const directQuery = virtualModule.type === "style" && /(?:[?&])direct(?:[=&]|$)/.test(source) ? "?direct" : "";
2172
+ return {
2173
+ id: `${resolveVirtualId(normalized)}${directQuery}`,
2174
+ moduleSideEffects: true
2175
+ };
2176
+ }
1561
2177
  const symbolSource = sourceForSymbolVirtualImporter(importer);
1562
2178
  if (symbolSource && isRelativeImport(source)) return await this.resolve(source, symbolSource, { skipSelf: true });
1563
2179
  const resumeSource = sourceForResumeVirtualImporter(importer);
@@ -1565,10 +2181,14 @@ function createMarklessRolldownPlugin(input) {
1565
2181
  return null;
1566
2182
  },
1567
2183
  load(id) {
1568
- if (normalizeVirtualId(id) === "virtual:markless:dev-log") return executionLogVirtualModuleSource({
1569
- moduleSizes: internalOptions.dev === true && getEnvironment(this) === "client" ? executionLogEstimatedSizes : void 0,
1570
- sizesUrl: internalOptions.dev === true ? void 0 : internalOptions.publicPath?.(MARKLESS_EXECUTION_SIZES) ?? `/${MARKLESS_EXECUTION_SIZES}`
1571
- });
2184
+ if (normalizeVirtualId(id) === "virtual:markless:dev-log") {
2185
+ const embedsDevSizes = internalOptions.dev === true && getEnvironment(this) === "client";
2186
+ return executionLogVirtualModuleSource({
2187
+ moduleSizes: embedsDevSizes ? executionLogEstimatedSizes : void 0,
2188
+ attribution: embedsDevSizes ? executionAttributionTables(transformManifests, getRoot(), importedChildren.values()) : void 0,
2189
+ sizesUrl: internalOptions.dev === true ? void 0 : internalOptions.publicPath?.(MARKLESS_EXECUTION_SIZES) ?? `/${MARKLESS_EXECUTION_SIZES}`
2190
+ });
2191
+ }
1572
2192
  const module = virtualModules.get(normalizeVirtualId(id));
1573
2193
  if (module) return virtualModuleSourceForLoad(module, {
1574
2194
  dev: internalOptions.dev === true && getEnvironment(this) === "client",
@@ -1592,15 +2212,54 @@ function createMarklessRolldownPlugin(input) {
1592
2212
  if (virtualId.startsWith("virtual:markless:")) return null;
1593
2213
  const source = pathname(id);
1594
2214
  clearSourceVirtualModules(source, virtualModules, sourceVirtualModules);
1595
- const transformed = await transformTsrxModule({
2215
+ let transformed = await transformTsrxModule({
2216
+ filename: source,
2217
+ source: code,
2218
+ buildId: internalOptions.buildId,
2219
+ executionLog: normalizeExecutionLogMode(internalOptions.executionLog),
2220
+ executionLogModuleHooks: internalOptions.dev === true && currentEnvironment === "client",
2221
+ inlineResumerDebug: internalOptions.inlineResumerDebug === true,
2222
+ environment: currentEnvironment,
2223
+ clientOutput: currentEnvironment === "client" && (clientSymbolEntrySources.has(source) || isSymbolOnlySourceRequest(id)) ? "symbols-only" : void 0,
2224
+ resumeModuleUrl: internalOptions.dev === true && currentEnvironment === "server" ? devBrowserSourceModuleUrl(source, getRoot(), internalOptions.publicPath) : void 0,
2225
+ styleModuleUrl: internalOptions.dev === true && currentEnvironment === "server" ? (virtualId) => withQuery(devBrowserVirtualModuleUrl(virtualId, internalOptions.publicPath), { direct: null }) : void 0,
2226
+ headInjections: internalOptions.dev === true && currentEnvironment === "server" ? internalOptions.devInjections : void 0,
2227
+ devResumeReexport: internalOptions.dev === true && currentEnvironment === "client"
2228
+ });
2229
+ registerTransformArtifacts({
2230
+ source,
2231
+ result: transformed,
2232
+ virtualModules,
2233
+ transformManifests,
2234
+ sourceVirtualModules,
2235
+ executionLogEstimatedSizes,
2236
+ dev,
2237
+ environment: currentEnvironment
2238
+ });
2239
+ const resolvedChildren = await resolveImportedChildren.call(this, source, transformed.manifest);
2240
+ for (const child of resolvedChildren) {
2241
+ importedChildren.set(importedChildKey(child), child);
2242
+ importedChildSources.add(child.source);
2243
+ }
2244
+ for (const child of resolvedChildren) {
2245
+ if (!transformManifests.has(child.source)) {
2246
+ if (internalOptions.dev === true) await internalOptions.devServer?.transformRequest(child.source, currentEnvironment);
2247
+ else if (typeof this.load === "function") await this.load({ id: child.source });
2248
+ }
2249
+ if (internalOptions.dev === true) validateImportedChild(child, transformManifests);
2250
+ }
2251
+ if (resolvedChildren.length > 0) transformed = await transformTsrxModule({
1596
2252
  filename: source,
1597
2253
  source: code,
1598
2254
  buildId: internalOptions.buildId,
2255
+ symbols: importedSymbolInputs(resolvedChildren, transformManifests),
1599
2256
  executionLog: normalizeExecutionLogMode(internalOptions.executionLog),
1600
2257
  executionLogModuleHooks: internalOptions.dev === true && currentEnvironment === "client",
2258
+ inlineResumerDebug: internalOptions.inlineResumerDebug === true,
1601
2259
  environment: currentEnvironment,
1602
2260
  clientOutput: currentEnvironment === "client" && (clientSymbolEntrySources.has(source) || isSymbolOnlySourceRequest(id)) ? "symbols-only" : void 0,
1603
2261
  resumeModuleUrl: internalOptions.dev === true && currentEnvironment === "server" ? devBrowserSourceModuleUrl(source, getRoot(), internalOptions.publicPath) : void 0,
2262
+ styleModuleUrl: internalOptions.dev === true && currentEnvironment === "server" ? (virtualId) => withQuery(devBrowserVirtualModuleUrl(virtualId, internalOptions.publicPath), { direct: null }) : void 0,
1604
2263
  headInjections: internalOptions.dev === true && currentEnvironment === "server" ? internalOptions.devInjections : void 0,
1605
2264
  devResumeReexport: internalOptions.dev === true && currentEnvironment === "client"
1606
2265
  });
@@ -1614,6 +2273,7 @@ function createMarklessRolldownPlugin(input) {
1614
2273
  dev,
1615
2274
  environment: currentEnvironment
1616
2275
  });
2276
+ for (const child of resolvedChildren) dev.record(child.source, [transformed.manifest.resolver.virtualModuleId], currentEnvironment);
1617
2277
  if (currentEnvironment === "client" && isResumeSourceRequest(id)) {
1618
2278
  const resumeModule = transformed.virtualModules.find((module) => module.type === "resume");
1619
2279
  if (resumeModule) return {
@@ -1621,16 +2281,24 @@ function createMarklessRolldownPlugin(input) {
1621
2281
  map: null
1622
2282
  };
1623
2283
  }
1624
- if (currentEnvironment === "client" && !internalOptions.dev) for (const module of transformed.virtualModules.filter((item) => item.type === "symbol" || item.type === "resume" && internalOptions.emitResumeModules === true && clientSymbolEntrySources.has(source))) this.emitFile({
1625
- type: "chunk",
1626
- id: module.id,
1627
- preserveSignature: "strict"
1628
- });
2284
+ if (currentEnvironment === "client" && !internalOptions.dev) for (const module of transformed.virtualModules.filter((item) => {
2285
+ if (item.type === "symbol") return true;
2286
+ if (item.type === "resolver") return (importedChildSources.has(source) || (transformed.manifest.captureMetadata?.boundResolverRows?.length ?? 0) > 0) && !emittedClientResolverSources.has(source);
2287
+ return item.type === "resume" && internalOptions.emitResumeModules === true && clientSymbolEntrySources.has(source);
2288
+ })) {
2289
+ this.emitFile({
2290
+ type: "chunk",
2291
+ id: module.id,
2292
+ preserveSignature: "strict"
2293
+ });
2294
+ if (module.type === "resolver") emittedClientResolverSources.add(source);
2295
+ }
1629
2296
  return transformed;
1630
2297
  },
1631
2298
  generateBundle: {
1632
2299
  order: "post",
1633
2300
  async handler(_, bundle) {
2301
+ for (const child of importedChildren.values()) validateImportedChild(child, transformManifests);
1634
2302
  if (getEnvironment(this) !== "client") return;
1635
2303
  stripEmptyPreloadWrappersFromChunks(bundle);
1636
2304
  const removedSymbolFacades = rewriteGeneratedSymbolFacadeImports(bundle);
@@ -1638,7 +2306,9 @@ function createMarklessRolldownPlugin(input) {
1638
2306
  compactGeneratedDirectSymbolLoaders(bundle);
1639
2307
  const manifestBundle = bundleWithoutRemovedChunks(bundle, removedSymbolFacades);
1640
2308
  const tableRewrite = rewriteGeneratedSymbolTableUrls(manifestBundle);
1641
- if (tableRewrite.unresolved.length > 0) this.error(`Markless symbol resolver table contains unresolved generated symbol chunks: ${tableRewrite.unresolved.join(", ")}`);
2309
+ if (tableRewrite.unresolved.length > 0) this.error(`Markless symbol resolver table contains unresolved generated symbol chunks: ${tableRewrite.unresolved.join(", ")}. markless debugging playbook: run pnpm doctor, or read agent/markless.md in the installed @markless/core package`);
2310
+ const tableIntegrity = verifyGeneratedSymbolTableRoutes(manifestBundle, transformManifests.values());
2311
+ if (tableIntegrity.errors.length > 0) this.error(`Markless symbol resolver table integrity check failed:\n${tableIntegrity.errors.map((error) => `- ${error.symbolId} -> ${error.claimedChunk}: ${error.reason}`).join("\n")}`);
1642
2312
  const clientManifest = createBuildMetadata(manifestBundle, transformManifests.values(), getRoot(), {
1643
2313
  bundleGraphAsset: MARKLESS_BUNDLE_GRAPH,
1644
2314
  bundleGraphAdders: internalOptions.bundleGraphAdders,
@@ -1657,7 +2327,7 @@ function createMarklessRolldownPlugin(input) {
1657
2327
  fileName: MARKLESS_BUNDLE_GRAPH,
1658
2328
  source: JSON.stringify(clientManifest.bundleGraph)
1659
2329
  });
1660
- this.emitFile(await createExecutionSizesAsset(manifestBundle, clientManifest, stripBuildPrefix));
2330
+ this.emitFile(await createExecutionSizesAsset(manifestBundle, clientManifest, stripBuildPrefix, executionLogInjection ? executionAttributionTables(transformManifests, getRoot(), importedChildren.values()) : void 0));
1661
2331
  this.emitFile({
1662
2332
  type: "asset",
1663
2333
  fileName: `${MARKLESS_BUILD_PREFIX}execution-demand.json`,
@@ -1667,6 +2337,88 @@ function createMarklessRolldownPlugin(input) {
1667
2337
  }
1668
2338
  };
1669
2339
  }
2340
+ async function resolveImportedChildren(parent, manifest) {
2341
+ return await Promise.all((manifest.symbolRoutes ?? []).map(async (route) => {
2342
+ const resolvedImport = await this.resolve(route.importSource, parent, { skipSelf: true });
2343
+ const resolvedId = typeof resolvedImport === "string" ? resolvedImport : resolvedImport && typeof resolvedImport === "object" && "id" in resolvedImport ? String(resolvedImport.id) : fallbackImportedSource(parent, route.importSource);
2344
+ return {
2345
+ parent,
2346
+ specifier: route.importSource,
2347
+ source: pathname(resolvedId),
2348
+ componentEdgeId: route.componentEdgeId
2349
+ };
2350
+ }));
2351
+ }
2352
+ function importedSymbolInputs(children, manifests) {
2353
+ return children.flatMap((child) => {
2354
+ const manifest = manifests.get(child.source);
2355
+ if (!manifest?.captureMetadata || !child.componentEdgeId) return [];
2356
+ return manifest.symbols.flatMap((symbol) => {
2357
+ const captureSymbol = manifest.captureMetadata?.extractedSymbols.find((candidate) => candidate.symbolId === symbol.symbolId);
2358
+ return captureSymbol?.captureSlots.some((slot) => slot.propName !== void 0) ? [{
2359
+ id: `imported:${encodeURIComponent(child.source)}:${symbol.symbolId}`,
2360
+ chunk: symbol.virtualModuleId,
2361
+ exportName: symbol.exportName,
2362
+ componentEdgeId: child.componentEdgeId,
2363
+ captureSymbol
2364
+ }] : [];
2365
+ });
2366
+ });
2367
+ }
2368
+ function fallbackImportedSource(parent, specifier) {
2369
+ const source = specifier.split("?")[0];
2370
+ return isRelativeImport(source) ? resolve(dirname(parent), source) : source;
2371
+ }
2372
+ function importedChildKey(child) {
2373
+ return `${child.parent}\0${child.specifier}\0${child.source}`;
2374
+ }
2375
+ function validateImportedChild(child, manifests) {
2376
+ const parentMetadata = manifests.get(child.parent)?.captureMetadata;
2377
+ const childMetadata = manifests.get(child.source)?.captureMetadata;
2378
+ if (!childMetadata && isPlainTypeScriptSource(child.source)) return;
2379
+ if (parentMetadata && childMetadata?.passId === parentMetadata.passId && Array.isArray(childMetadata.extractedSymbols) && Array.isArray(childMetadata.diagnostics)) return;
2380
+ throw new Error(`MARKLESS_CAPTURE_METADATA_MISSING: Parent module ${JSON.stringify(child.parent)} composes imported child ${JSON.stringify(child.specifier)}, but its compiled artifact has no current capture metadata. Rebuild the child with the current Markless compiler and clear any stale build cache.`);
2381
+ }
2382
+ function isPlainTypeScriptSource(source) {
2383
+ return /\.[cm]?tsx?$/.test(source);
2384
+ }
2385
+ function executionAttributionRoots(manifests, childrenByRoute) {
2386
+ const children = /* @__PURE__ */ new Set();
2387
+ for (const manifest of manifests.values()) for (const route of manifest.symbolRoutes ?? []) {
2388
+ const child = resolvedRouteSource(manifest.source, route.importSource, childrenByRoute);
2389
+ if (manifests.has(child)) children.add(child);
2390
+ }
2391
+ return [...manifests.keys()].filter((source) => !children.has(source));
2392
+ }
2393
+ function executionAttributionTables(manifests, root, children) {
2394
+ const childrenByRoute = new Map([...children].map((child) => [routeKey(child.parent, child.specifier), child.source]));
2395
+ return Object.fromEntries(executionAttributionRoots(manifests, childrenByRoute).sort().map((source) => [executionAttributionRouteKey(source, root), flattenExecutionAttributionScopes(source, manifests, childrenByRoute)]));
2396
+ }
2397
+ function executionAttributionRouteKey(source, root) {
2398
+ const prefix = root ? `${root.replace(/[/\\]+$/, "")}/` : "";
2399
+ return (prefix && source.startsWith(prefix) ? source.slice(prefix.length) : source).replace(/^[/\\]+/, "");
2400
+ }
2401
+ function flattenExecutionAttributionScopes(root, manifests, childrenByRoute) {
2402
+ const scopes = {};
2403
+ const visit = (source, scope, seen) => {
2404
+ if (seen.has(source)) return;
2405
+ scopes[scope] = encodedSymbolSource(source);
2406
+ const manifest = manifests.get(source);
2407
+ for (const route of manifest?.symbolRoutes ?? []) {
2408
+ const child = resolvedRouteSource(source, route.importSource, childrenByRoute);
2409
+ if (!manifests.has(child)) continue;
2410
+ visit(child, scope + route.prefix, new Set([...seen, source]));
2411
+ }
2412
+ };
2413
+ visit(root, "", /* @__PURE__ */ new Set());
2414
+ return scopes;
2415
+ }
2416
+ function resolvedRouteSource(parent, specifier, childrenByRoute) {
2417
+ return childrenByRoute.get(routeKey(parent, specifier)) ?? fallbackImportedSource(parent, specifier);
2418
+ }
2419
+ function routeKey(parent, specifier) {
2420
+ return `${parent}\0${specifier}`;
2421
+ }
1670
2422
  function bundleWithoutRemovedChunks(bundle, removedFileNames) {
1671
2423
  if (removedFileNames.size === 0) return bundle;
1672
2424
  const next = {};
@@ -1799,4 +2551,4 @@ function pathname(id) {
1799
2551
  return parsePath(id).pathname;
1800
2552
  }
1801
2553
  //#endregion
1802
- export { transformTsrxModule as a, convertManifestToBundleGraph as c, marklessServer as i, createPreloadGraphAdder as l, marklessClient as n, createBuildMetadata as o, marklessLib as r, collectHeadLinkInjections as s, createMarklessRolldownPlugin as t };
2554
+ export { preflightTsrxModuleDiagnostics as a, collectHeadLinkInjections as c, marklessServer as i, convertManifestToBundleGraph as l, marklessClient as n, transformTsrxModule as o, marklessLib as r, createBuildMetadata as s, createMarklessRolldownPlugin as t, createPreloadGraphAdder as u };