veryfront 0.1.739 → 0.1.742

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.
Files changed (58) hide show
  1. package/esm/deno.js +1 -1
  2. package/esm/src/agent/hosted/child-tool-input.js +1 -1
  3. package/esm/src/mcp/http-transport.js +1 -1
  4. package/esm/src/mcp/session.d.ts +23 -0
  5. package/esm/src/mcp/session.d.ts.map +1 -1
  6. package/esm/src/mcp/session.js +46 -3
  7. package/esm/src/modules/manifest/route-module-manifest.d.ts.map +1 -1
  8. package/esm/src/modules/manifest/route-module-manifest.js +12 -4
  9. package/esm/src/modules/react-loader/ssr-module-loader/cross-project-import-loader.d.ts.map +1 -1
  10. package/esm/src/modules/react-loader/ssr-module-loader/cross-project-import-loader.js +2 -1
  11. package/esm/src/modules/server/cross-project-source-limit.d.ts +7 -0
  12. package/esm/src/modules/server/cross-project-source-limit.d.ts.map +1 -0
  13. package/esm/src/modules/server/cross-project-source-limit.js +46 -0
  14. package/esm/src/modules/server/module-batch-handler.d.ts.map +1 -1
  15. package/esm/src/modules/server/module-batch-handler.js +3 -4
  16. package/esm/src/modules/server/module-server.d.ts.map +1 -1
  17. package/esm/src/modules/server/module-server.js +11 -1
  18. package/esm/src/oauth/providers/base.d.ts +3 -0
  19. package/esm/src/oauth/providers/base.d.ts.map +1 -1
  20. package/esm/src/oauth/providers/base.js +24 -2
  21. package/esm/src/provider/runtime-loader/tool-input-status.d.ts.map +1 -1
  22. package/esm/src/provider/runtime-loader/tool-input-status.js +16 -8
  23. package/esm/src/rendering/orchestrator/module-loader/dependency-resolver.d.ts +2 -0
  24. package/esm/src/rendering/orchestrator/module-loader/dependency-resolver.d.ts.map +1 -1
  25. package/esm/src/rendering/orchestrator/module-loader/dependency-resolver.js +23 -10
  26. package/esm/src/rendering/renderer-concurrency.d.ts.map +1 -1
  27. package/esm/src/rendering/renderer-concurrency.js +9 -2
  28. package/esm/src/security/sandbox/worker-permissions.d.ts +10 -7
  29. package/esm/src/security/sandbox/worker-permissions.d.ts.map +1 -1
  30. package/esm/src/security/sandbox/worker-permissions.js +32 -18
  31. package/esm/src/server/services/rendering/ssr.service.d.ts.map +1 -1
  32. package/esm/src/server/services/rendering/ssr.service.js +6 -3
  33. package/esm/src/transforms/mdx/esm-module-loader/loader-helpers.d.ts +4 -0
  34. package/esm/src/transforms/mdx/esm-module-loader/loader-helpers.d.ts.map +1 -1
  35. package/esm/src/transforms/mdx/esm-module-loader/loader-helpers.js +22 -18
  36. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/http-fetcher.d.ts.map +1 -1
  37. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/http-fetcher.js +27 -8
  38. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/import-rewriter.d.ts.map +1 -1
  39. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/import-rewriter.js +24 -14
  40. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/index.d.ts +1 -1
  41. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/index.d.ts.map +1 -1
  42. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/index.js +1 -1
  43. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.d.ts +4 -0
  44. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.d.ts.map +1 -1
  45. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.js +45 -37
  46. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/render-sessions.d.ts +5 -0
  47. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/render-sessions.d.ts.map +1 -1
  48. package/esm/src/transforms/mdx/esm-module-loader/module-fetcher/render-sessions.js +27 -2
  49. package/esm/src/transforms/mdx/esm-module-loader/types.d.ts +2 -0
  50. package/esm/src/transforms/mdx/esm-module-loader/types.d.ts.map +1 -1
  51. package/esm/src/transforms/mdx/esm-module-loader/utils/source-spans.d.ts +23 -0
  52. package/esm/src/transforms/mdx/esm-module-loader/utils/source-spans.d.ts.map +1 -0
  53. package/esm/src/transforms/mdx/esm-module-loader/utils/source-spans.js +188 -0
  54. package/esm/src/utils/version-constant.d.ts +1 -1
  55. package/esm/src/utils/version-constant.js +1 -1
  56. package/esm/src/workflow/worker/workflow-worker.d.ts.map +1 -1
  57. package/esm/src/workflow/worker/workflow-worker.js +9 -1
  58. package/package.json +1 -1
@@ -6,11 +6,10 @@
6
6
  *
7
7
  * @module security/sandbox/worker-permissions
8
8
  */
9
- /**
10
- * Deno Worker permission object.
11
- * See: https://docs.deno.com/runtime/fundamentals/permissions/
12
- */
13
9
  import * as dntShim from "../../../_dnt.shims.js";
10
+ import { getFrameworkRootFromMeta } from "../../platform/compat/vfs-paths.js";
11
+ import { getHostEnv } from "../../platform/compat/process.js";
12
+ import { getCacheBaseDir, getHttpBundleCacheDir, getMdxEsmCacheDir, } from "../../utils/cache-dir.js";
14
13
  // Cache compiled binary check — Deno.execPath() is a syscall that never changes at runtime
15
14
  const _isCompiledBinary = (() => {
16
15
  try {
@@ -24,6 +23,27 @@ const _isCompiledBinary = (() => {
24
23
  return false;
25
24
  }
26
25
  })();
26
+ function normalizeReadPaths(paths) {
27
+ const unique = new Set();
28
+ for (const path of paths) {
29
+ if (!path)
30
+ continue;
31
+ const trimmed = path.trim();
32
+ if (!trimmed)
33
+ continue;
34
+ unique.add(trimmed);
35
+ }
36
+ return [...unique];
37
+ }
38
+ function getDefaultCompiledReadPaths() {
39
+ return normalizeReadPaths([
40
+ getFrameworkRootFromMeta(globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url),
41
+ getCacheBaseDir(),
42
+ getMdxEsmCacheDir(),
43
+ getHttpBundleCacheDir(),
44
+ getHostEnv("DENO_DIR"),
45
+ ]);
46
+ }
27
47
  /**
28
48
  * Build scoped permissions for a project worker.
29
49
  *
@@ -35,20 +55,14 @@ const _isCompiledBinary = (() => {
35
55
  * - ffi: denied (no native code from user code)
36
56
  * - sys: denied (no system info access from user code)
37
57
  */
38
- export function buildWorkerPermissions(readPaths) {
39
- // In compiled binaries, user modules import from the VFS temp dir which
40
- // is outside the project directory. Rather than trying to enumerate all
41
- // read paths, grant full read access — the security boundary is enforced
42
- // by denying write/run/ffi/sys, not by restricting reads.
43
- //
44
- // SECURITY (residual, tracked in #2245): with read:true a user route
45
- // handler can call Deno.readTextFile directly to read any host file,
46
- // bypassing the project-scoped ctx.fs adapter. Narrowing this to a
47
- // binary-validated allow-list (or removing direct Deno fs from user module
48
- // scope) is blocking work for the next security batch.
49
- if (_isCompiledBinary) {
58
+ export function buildWorkerPermissions(readPaths, options = {}) {
59
+ const isCompiledBinary = options.isCompiledBinary ?? _isCompiledBinary;
60
+ const normalizedReadPaths = normalizeReadPaths(readPaths);
61
+ if (isCompiledBinary) {
62
+ const compiledReadPaths = options.compiledReadPaths ?? getDefaultCompiledReadPaths();
63
+ const scopedReadPaths = normalizeReadPaths([...normalizedReadPaths, ...compiledReadPaths]);
50
64
  return {
51
- read: true,
65
+ read: scopedReadPaths.length > 0 ? scopedReadPaths : false,
52
66
  write: false,
53
67
  net: true,
54
68
  env: true,
@@ -58,7 +72,7 @@ export function buildWorkerPermissions(readPaths) {
58
72
  };
59
73
  }
60
74
  return {
61
- read: readPaths.length > 0 ? readPaths : false,
75
+ read: normalizedReadPaths.length > 0 ? normalizedReadPaths : false,
62
76
  write: false,
63
77
  net: true,
64
78
  env: true,
@@ -1 +1 @@
1
- {"version":3,"file":"ssr.service.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/services/rendering/ssr.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,kCAAkC,CAAC;AAsB1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAItE;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC5D;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,mBAAmB,IAAI,YAAY,CAAC;IACpC,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACrF,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC;CAC3D;AAUD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,UAAU,GAAG,OAAO,CAAC;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,SAAS,CAAC,EAAE,WAAW,GAAG,YAAY,GAAG,UAAU,GAAG,cAAc,GAAG,SAAS,CAAC;IACjF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AAqBD,qBAAa,UAAW,YAAW,cAAc;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAA0B;IACrD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;gBAExC,OAAO,CAAC,EAAE;QACpB,SAAS,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;QACpC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;KACrC;IAKD,mBAAmB,IAAI,YAAY;IAW7B,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAI1D,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IA2G1F,OAAO,CAAC,iBAAiB;IAyHzB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;CAS1D"}
1
+ {"version":3,"file":"ssr.service.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/services/rendering/ssr.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,kCAAkC,CAAC;AAuB1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAItE;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC5D;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,mBAAmB,IAAI,YAAY,CAAC;IACpC,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACrF,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAC;CAC3D;AAUD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,UAAU,GAAG,OAAO,CAAC;IACpC,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,SAAS,CAAC,EAAE,WAAW,GAAG,YAAY,GAAG,UAAU,GAAG,cAAc,GAAG,SAAS,CAAC;IACjF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AAqBD,qBAAa,UAAW,YAAW,cAAc;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAA0B;IACrD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;gBAExC,OAAO,CAAC,EAAE;QACpB,SAAS,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;QACpC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;KACrC;IAKD,mBAAmB,IAAI,YAAY;IAW7B,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAI1D,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IA+G1F,OAAO,CAAC,iBAAiB;IAyHzB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;CAS1D"}
@@ -4,7 +4,7 @@ import { serverLogger, timeAsync } from "../../../utils/index.js";
4
4
  import { computeSSRETag } from "../../handlers/request/ssr/etag-handler.js";
5
5
  import { VeryfrontError } from "../../../errors/index.js";
6
6
  import { getColorSchemeFromRequest } from "../../../security/http/client-hints.js";
7
- import { endRenderSession, hasRenderSession, startRenderSession, } from "../../../transforms/mdx/esm-module-loader/module-fetcher/index.js";
7
+ import { endRenderSession, hasRenderSession, runInRenderSession, startRenderSession, } from "../../../transforms/mdx/esm-module-loader/module-fetcher/index.js";
8
8
  import { getErrorCollector } from "../../../observability/error-collector.js";
9
9
  import { profilePhase } from "../../../observability/request-profiler.js";
10
10
  import { ErrorOverlay, parseErrorLocation } from "../../dev-server/error-overlay/index.js";
@@ -68,7 +68,10 @@ export class SSRService {
68
68
  slug,
69
69
  });
70
70
  const renderStartTime = performance.now();
71
- const result = await profilePhase("ssr.render_page", () => timeAsync("render-page", () => renderer.renderPage(slug, {
71
+ // Bind the render session to this async context so modules fetched
72
+ // during the render are attributed to THIS render, not whichever
73
+ // concurrent session started first.
74
+ const result = await runInRenderSession(renderSessionId, () => profilePhase("ssr.render_page", () => timeAsync("render-page", () => renderer.renderPage(slug, {
72
75
  delivery: "stream",
73
76
  request,
74
77
  url,
@@ -84,7 +87,7 @@ export class SSRService {
84
87
  noHmr,
85
88
  forceProductionScripts: options.forceProductionScripts,
86
89
  renderSessionId,
87
- })));
90
+ }))));
88
91
  logger.debug("renderPage DONE", {
89
92
  projectSlug: ctx.projectSlug,
90
93
  slug,
@@ -25,6 +25,8 @@ export declare function initializeCacheDir(context: ESMLoaderContext): Promise<s
25
25
  export declare function findVfModuleImports(code: string): Array<{
26
26
  original: string;
27
27
  path: string;
28
+ start: number;
29
+ end: number;
28
30
  }>;
29
31
  /**
30
32
  * Process /_vf_modules/ imports and replace them with file:// paths.
@@ -32,5 +34,7 @@ export declare function findVfModuleImports(code: string): Array<{
32
34
  export declare function processVfModuleImports(code: string, imports: Array<{
33
35
  original: string;
34
36
  path: string;
37
+ start: number;
38
+ end: number;
35
39
  }>, context: ESMLoaderContext, projectDir: string, strictMissingModules: boolean): Promise<string>;
36
40
  //# sourceMappingURL=loader-helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader-helpers.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/esm-module-loader/loader-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;GAGG;AACH,wBAAsB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAapF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAWnE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgCnF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAW3F;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,OAAO,EAAE,gBAAgB,EACzB,UAAU,EAAE,MAAM,EAClB,oBAAoB,EAAE,OAAO,GAC5B,OAAO,CAAC,MAAM,CAAC,CAwGjB"}
1
+ {"version":3,"file":"loader-helpers.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/mdx/esm-module-loader/loader-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmBH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;GAGG;AACH,wBAAsB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAapF;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAWnE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgCnF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,GACX,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAKvE;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,KAAK,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,EAC9E,OAAO,EAAE,gBAAgB,EACzB,UAAU,EAAE,MAAM,EAClB,oBAAoB,EAAE,OAAO,GAC5B,OAAO,CAAC,MAAM,CAAC,CAoHjB"}
@@ -17,6 +17,7 @@ import { exists as fsExists } from "../../../platform/compat/fs.js";
17
17
  import { LOG_PREFIX_MDX_LOADER } from "./constants.js";
18
18
  import { getLocalFs } from "./cache/index.js";
19
19
  import { createStubModule } from "./utils/stub-module.js";
20
+ import { findStaticImportFromSpans, replaceSourceSpans, } from "./utils/source-spans.js";
20
21
  import { createModuleFetcherContext, fetchAndCacheModule } from "./module-fetcher/index.js";
21
22
  import { buildMissingModuleError } from "./missing-module.js";
22
23
  /**
@@ -89,15 +90,7 @@ export async function initializeCacheDir(context) {
89
90
  * Find /_vf_modules/ imports in code.
90
91
  */
91
92
  export function findVfModuleImports(code) {
92
- const imports = [];
93
- const pattern = /from\s*["'](\/?)(_vf_modules\/[^"']+)["']/g;
94
- let match;
95
- while ((match = pattern.exec(code)) !== null) {
96
- const [original, , path] = match;
97
- if (path)
98
- imports.push({ original, path });
99
- }
100
- return imports;
93
+ return findStaticImportFromSpans(code, (specifier) => specifier.match(/^\/?(_vf_modules\/[^?]+)(?:\?.*)?$/)?.[1]);
101
94
  }
102
95
  /**
103
96
  * Process /_vf_modules/ imports and replace them with file:// paths.
@@ -136,7 +129,7 @@ export async function processVfModuleImports(code, imports, context, projectDir,
136
129
  strictMissingModules,
137
130
  });
138
131
  const fetchStart = performance.now();
139
- const results = await Promise.all(imports.map(async ({ original, path }, index) => {
132
+ const results = await Promise.all(imports.map(async ({ original, path, start, end }, index) => {
140
133
  return await withSpan(SpanNames.MDX_FETCH_MODULE, async () => {
141
134
  const moduleStart = performance.now();
142
135
  logger.debug(`${LOG_PREFIX_MDX_LOADER} Fetching module START`, {
@@ -151,7 +144,7 @@ export async function processVfModuleImports(code, imports, context, projectDir,
151
144
  path,
152
145
  durationMs: (performance.now() - moduleStart).toFixed(1),
153
146
  });
154
- return { original, filePath, path };
147
+ return { original, start, end, filePath, path };
155
148
  }, {
156
149
  "mdx.module_path": path,
157
150
  "mdx.module_index": index,
@@ -163,10 +156,15 @@ export async function processVfModuleImports(code, imports, context, projectDir,
163
156
  moduleCount: imports.length,
164
157
  durationMs: (performance.now() - fetchStart).toFixed(1),
165
158
  });
166
- let result = code;
167
- for (const { original, filePath, path } of results) {
159
+ const replacements = [];
160
+ for (const { original, start, end, filePath, path } of results) {
168
161
  if (filePath) {
169
- result = result.replace(original, `from "file://${filePath}"`);
162
+ replacements.push({
163
+ start,
164
+ end,
165
+ expected: original,
166
+ replacement: `from "file://${filePath}"`,
167
+ });
170
168
  continue;
171
169
  }
172
170
  if (strictMissingModules) {
@@ -178,9 +176,15 @@ export async function processVfModuleImports(code, imports, context, projectDir,
178
176
  projectSlug,
179
177
  });
180
178
  }
181
- const stubPath = await createStubModule(path, result, original, context.esmCacheDir);
182
- if (stubPath)
183
- result = result.replace(original, `from "file://${stubPath}"`);
179
+ const stubPath = await createStubModule(path, code, original, context.esmCacheDir);
180
+ if (stubPath) {
181
+ replacements.push({
182
+ start,
183
+ end,
184
+ expected: original,
185
+ replacement: `from "file://${stubPath}"`,
186
+ });
187
+ }
184
188
  }
185
- return result;
189
+ return replaceSourceSpans(code, replacements);
186
190
  }
@@ -1 +1 @@
1
- {"version":3,"file":"http-fetcher.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/http-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAGjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAK5E;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,cAAc,EACvB,qBAAqB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,EAChF,GAAG,EAAE,MAAM,EACX,WAAW,CAAC,EAAE,MAAM,EACpB,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqDxB"}
1
+ {"version":3,"file":"http-fetcher.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/http-fetcher.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAGjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAM5E;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,cAAc,EACvB,qBAAqB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,EAChF,GAAG,EAAE,MAAM,EACX,WAAW,CAAC,EAAE,MAAM,EACpB,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuExB"}
@@ -11,6 +11,7 @@ import { SpanNames } from "../../../../observability/tracing/span-names.js";
11
11
  import { LOG_PREFIX_MDX_LOADER } from "../constants.js";
12
12
  import { rewriteVeryfrontImports } from "./import-rewriter.js";
13
13
  import { findNestedImports } from "./nested-imports.js";
14
+ import { replaceSourceSpans } from "../utils/source-spans.js";
14
15
  /**
15
16
  * Fetch module via HTTP as a fallback (local development only).
16
17
  *
@@ -38,20 +39,38 @@ export async function fetchModuleViaHTTP(normalizedPath, adapter, fetchAndCacheM
38
39
  log.warn(`${LOG_PREFIX_MDX_LOADER} HTTP fetch also failed: ${moduleUrl} (${response.status})`);
39
40
  return null;
40
41
  }
41
- let moduleCode = rewriteVeryfrontImports(await response.text());
42
+ const moduleCode = rewriteVeryfrontImports(await response.text());
42
43
  const { vfModules, relative } = findNestedImports(moduleCode);
43
44
  const allImports = [
44
- ...vfModules.map(({ original, path }) => ({ original, path, key: "nestedPath" })),
45
- ...relative.map(({ original, path }) => ({ original, path, key: "relativePath" })),
45
+ ...vfModules.map(({ original, path, start, end }) => ({
46
+ original,
47
+ path,
48
+ start,
49
+ end,
50
+ key: "nestedPath",
51
+ })),
52
+ ...relative.map(({ original, path, start, end }) => ({
53
+ original,
54
+ path,
55
+ start,
56
+ end,
57
+ key: "relativePath",
58
+ })),
46
59
  ];
47
- const results = await Promise.all(allImports.map(async ({ original, path, key }) => {
60
+ const results = await Promise.all(allImports.map(async ({ original, path, start, end, key }) => {
48
61
  const nestedFilePath = await fetchAndCacheModuleFn(path, normalizedPath);
49
- return { original, nestedFilePath, [key]: path };
62
+ return { original, start, end, nestedFilePath, [key]: path };
50
63
  }));
51
- for (const { original, nestedFilePath } of results) {
64
+ const replacements = [];
65
+ for (const { original, start, end, nestedFilePath } of results) {
52
66
  if (nestedFilePath) {
53
- moduleCode = moduleCode.replace(original, `from "file://${nestedFilePath}"`);
67
+ replacements.push({
68
+ start,
69
+ end,
70
+ expected: original,
71
+ replacement: `from "file://${nestedFilePath}"`,
72
+ });
54
73
  }
55
74
  }
56
- return moduleCode;
75
+ return replaceSourceSpans(moduleCode, replacements);
57
76
  }
@@ -1 +1 @@
1
- {"version":3,"file":"import-rewriter.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/import-rewriter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5D;AAwCD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8C7F"}
1
+ {"version":3,"file":"import-rewriter.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/import-rewriter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgB5D;AAwCD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0D7F"}
@@ -7,17 +7,24 @@ import { dirname, join, resolve } from "../../../../platform/compat/path/index.j
7
7
  import { FRAMEWORK_ROOT } from "../constants.js";
8
8
  import { resolveVeryfrontModuleUrl } from "../../../veryfront-module-urls.js";
9
9
  import { getLocalFs } from "../cache/index.js";
10
+ import { findStaticImportFromSpans, findStaticSideEffectImportSpans, replaceSourceSpans, } from "../utils/source-spans.js";
10
11
  /**
11
12
  * Rewrite veryfront/* imports to /_vf_modules/_veryfront/ paths for MDX module loading.
12
13
  * Uses deno.json exports/imports as the source of truth and appends ?ssr=true.
13
14
  */
14
15
  export function rewriteVeryfrontImports(code) {
15
- return code.replace(/from\s*["'](veryfront\/[^"']+)["']/g, (_match, specifier) => {
16
- const mapped = resolveVeryfrontModuleUrl(specifier);
16
+ const replacements = findStaticImportFromSpans(code, (specifier) => specifier.startsWith("veryfront/") ? specifier : null).flatMap(({ original, path, start, end }) => {
17
+ const mapped = resolveVeryfrontModuleUrl(path);
17
18
  if (!mapped)
18
- return `from "${specifier}"`;
19
- return `from "${mapped}?ssr=true"`;
19
+ return [];
20
+ return [{
21
+ start,
22
+ end,
23
+ expected: original,
24
+ replacement: `from "${mapped}?ssr=true"`,
25
+ }];
20
26
  });
27
+ return replaceSourceSpans(code, replacements);
21
28
  }
22
29
  /**
23
30
  * Rewrite relative imports in framework files to absolute file:// paths.
@@ -72,27 +79,30 @@ export async function rewriteDntImports(code, sourceFilePath) {
72
79
  let rewritten = code;
73
80
  const patterns = [
74
81
  {
75
- regex: /from\s*["'](\.\.?\/[^"']+)["']/g,
82
+ findMatches: (source) => findStaticImportFromSpans(source, (specifier) => specifier.match(/^(\.\.?\/[^?]+)(?:\?.*)?$/)?.[1]),
76
83
  buildReplacement: (path) => `from "file://${path}"`,
77
84
  },
78
85
  {
79
- regex: /import\s*["'](\.\.?\/[^"']+)["']/g,
86
+ findMatches: (source) => findStaticSideEffectImportSpans(source, (specifier) => specifier.match(/^(\.\.?\/[^?]+)(?:\?.*)?$/)?.[1]),
80
87
  buildReplacement: (path) => `import "file://${path}"`,
81
88
  },
82
89
  ];
83
- for (const { regex, buildReplacement } of patterns) {
84
- const matches = [...rewritten.matchAll(regex)];
85
- for (const match of matches) {
86
- const original = match[0];
87
- const relativePath = match[1];
88
- if (!relativePath)
89
- continue;
90
+ for (const { findMatches, buildReplacement } of patterns) {
91
+ const matches = findMatches(rewritten);
92
+ const replacements = [];
93
+ for (const { original, path: relativePath, start, end } of matches) {
90
94
  const absolutePath = resolve(sourceDir, relativePath);
91
95
  const resolvedPath = needsFrameworkSourceFallback
92
96
  ? await findExistingFrameworkRelativeTarget(absolutePath) ?? absolutePath
93
97
  : absolutePath;
94
- rewritten = rewritten.replace(original, buildReplacement(resolvedPath));
98
+ replacements.push({
99
+ start,
100
+ end,
101
+ expected: original,
102
+ replacement: buildReplacement(resolvedPath),
103
+ });
95
104
  }
105
+ rewritten = replaceSourceSpans(rewritten, replacements);
96
106
  }
97
107
  return rewritten;
98
108
  }
@@ -15,7 +15,7 @@ import type { Logger } from "../../../../utils/logger/logger.js";
15
15
  import type { RuntimeAdapter } from "../../../../platform/adapters/base.js";
16
16
  import type { ModuleFetcherContext } from "../types.js";
17
17
  export { rewriteDntImports } from "./import-rewriter.js";
18
- export { endRenderSession, hasRenderSession, startRenderSession } from "./render-sessions.js";
18
+ export { endRenderSession, hasRenderSession, runInRenderSession, startRenderSession, } from "./render-sessions.js";
19
19
  /**
20
20
  * Error thrown when transform tree exceeds the timeout.
21
21
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAG5E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAcxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAS9F;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAOtD;AAED;;GAEG;AACH,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,SAAS,EAAE,MAAM;CAI9B;AAcD;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,oBAAoB,EAC7B,gBAAgB,CAAC,EAAE,MAAM,EACzB,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAC/B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwFxB;AA6KD;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;IACR,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,GACA,oBAAoB,CAUtB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAG5E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAcxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAS9B;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAOtD;AAED;;GAEG;AACH,qBAAa,6BAA8B,SAAQ,KAAK;gBAC1C,SAAS,EAAE,MAAM;CAI9B;AAcD;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,oBAAoB,EAC7B,gBAAgB,CAAC,EAAE,MAAM,EACzB,OAAO,GAAE,GAAG,CAAC,MAAM,CAAa,GAC/B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwFxB;AA6KD;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;IACR,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,GACA,oBAAoB,CAUtB"}
@@ -27,7 +27,7 @@ import { readValidCachedModulePath } from "./path-cache-lookup.js";
27
27
  import { transformResolvedModuleSource } from "./source-transform.js";
28
28
  // Re-export extracted modules for backward compatibility
29
29
  export { rewriteDntImports } from "./import-rewriter.js";
30
- export { endRenderSession, hasRenderSession, startRenderSession } from "./render-sessions.js";
30
+ export { endRenderSession, hasRenderSession, runInRenderSession, startRenderSession, } from "./render-sessions.js";
31
31
  /**
32
32
  * Maximum time allowed for the entire transform tree (recursive module resolution).
33
33
  * If the cumulative time exceeds this, we fail fast instead of hanging indefinitely.
@@ -13,10 +13,14 @@ export declare function findNestedImports(moduleCode: string): {
13
13
  vfModules: Array<{
14
14
  original: string;
15
15
  path: string;
16
+ start: number;
17
+ end: number;
16
18
  }>;
17
19
  relative: Array<{
18
20
  original: string;
19
21
  path: string;
22
+ start: number;
23
+ end: number;
20
24
  }>;
21
25
  };
22
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"nested-imports.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAEjE;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GACjB;IACD,SAAS,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,QAAQ,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrD,CAqBA;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAO3F;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,EAAE,EAC7B,WAAW,EAAE,MAAM,EACnB,oBAAoB,EAAE,OAAO,EAC7B,gBAAgB,CAAC,EAAE,MAAM,EACzB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED,MAAM,WAAW,+BAA+B;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,+BAA+B,GACrC,OAAO,CAAC,MAAM,CAAC,CAwEjB"}
1
+ {"version":3,"file":"nested-imports.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/nested-imports.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAEjE;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GACjB;IACD,SAAS,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjF,QAAQ,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjF,CAkCA;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAO3F;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,EAAE,EAC7B,WAAW,EAAE,MAAM,EACnB,oBAAoB,EAAE,OAAO,EAC7B,gBAAgB,CAAC,EAAE,MAAM,EACzB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAqCjB;AAED,MAAM,WAAW,+BAA+B;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,+BAA+B,GACrC,OAAO,CAAC,MAAM,CAAC,CAuDjB"}
@@ -3,8 +3,9 @@
3
3
  *
4
4
  * @module transforms/mdx/esm-module-loader/module-fetcher/nested-imports
5
5
  */
6
- import { LOG_PREFIX_MDX_LOADER, RELATIVE_IMPORT_PATTERN, UNRESOLVED_VF_MODULES_PATTERN, VF_MODULE_IMPORT_PATTERN, } from "../constants.js";
6
+ import { LOG_PREFIX_MDX_LOADER, UNRESOLVED_VF_MODULES_PATTERN } from "../constants.js";
7
7
  import { createStubModule } from "../utils/stub-module.js";
8
+ import { findStaticImportFromSpans, replaceSourceSpans, } from "../utils/source-spans.js";
8
9
  import { buildMissingModuleError } from "../missing-module.js";
9
10
  /**
10
11
  * Find nested module imports in code.
@@ -13,20 +14,22 @@ import { buildMissingModuleError } from "../missing-module.js";
13
14
  export function findNestedImports(moduleCode) {
14
15
  const vfModules = [];
15
16
  const relative = [];
16
- const vfPattern = new RegExp(VF_MODULE_IMPORT_PATTERN.source, "g");
17
- let match;
18
- while ((match = vfPattern.exec(moduleCode)) !== null) {
19
- const rawPath = match[1];
17
+ for (const { original, path: rawPath, start, end } of findStaticImportFromSpans(moduleCode, (specifier) => specifier.match(/^((?:file:\/\/)?\/?\/?_vf_modules\/[^?]+)(?:\?.*)?$/)?.[1])) {
20
18
  // Strip file:// prefix and leading slashes to get clean _vf_modules/... path
21
- if (rawPath) {
22
- vfModules.push({ original: match[0], path: rawPath.replace(/^(?:file:\/\/)?\/+/, "") });
23
- }
19
+ vfModules.push({
20
+ original,
21
+ path: rawPath.replace(/^(?:file:\/\/)?\/+/, ""),
22
+ start,
23
+ end,
24
+ });
24
25
  }
25
- const relativePattern = new RegExp(RELATIVE_IMPORT_PATTERN.source, "g");
26
- while ((match = relativePattern.exec(moduleCode)) !== null) {
27
- const path = match[1];
28
- if (path)
29
- relative.push({ original: match[0], path });
26
+ for (const { original, path, start, end } of findStaticImportFromSpans(moduleCode, (specifier) => specifier.match(/^(\.\.?\/[^?]+)(?:\?.*)?$/)?.[1])) {
27
+ relative.push({
28
+ original,
29
+ path,
30
+ start,
31
+ end,
32
+ });
30
33
  }
31
34
  return { vfModules, relative };
32
35
  }
@@ -45,10 +48,15 @@ export function hasUnresolvedImports(moduleCode) {
45
48
  * Process nested imports by replacing them with file:// paths or stub modules.
46
49
  */
47
50
  export async function processNestedImports(moduleCode, results, esmCacheDir, strictMissingModules, parentModulePath, projectSlug) {
48
- let result = moduleCode;
49
- for (const { original, nestedFilePath, nestedPath, relativePath } of results) {
51
+ const replacements = [];
52
+ for (const { original, start, end, nestedFilePath, nestedPath, relativePath } of results) {
50
53
  if (nestedFilePath) {
51
- result = result.replace(original, `from "file://${nestedFilePath}"`);
54
+ replacements.push({
55
+ start,
56
+ end,
57
+ expected: original,
58
+ replacement: `from "file://${nestedFilePath}"`,
59
+ });
52
60
  continue;
53
61
  }
54
62
  const modulePath = nestedPath || relativePath || "";
@@ -61,17 +69,23 @@ export async function processNestedImports(moduleCode, results, esmCacheDir, str
61
69
  projectSlug,
62
70
  });
63
71
  }
64
- const stubPath = await createStubModule(modulePath, result, original, esmCacheDir);
65
- if (stubPath)
66
- result = result.replace(original, `from "file://${stubPath}"`);
72
+ const stubPath = await createStubModule(modulePath, moduleCode, original, esmCacheDir);
73
+ if (stubPath) {
74
+ replacements.push({
75
+ start,
76
+ end,
77
+ expected: original,
78
+ replacement: `from "file://${stubPath}"`,
79
+ });
80
+ }
67
81
  }
68
- return result;
82
+ return replaceSourceSpans(moduleCode, replacements);
69
83
  }
70
84
  /**
71
85
  * Resolve nested /_vf_modules and relative imports into local file:// cache paths.
72
86
  */
73
87
  export async function resolveNestedModuleImports(input) {
74
- let moduleCode = input.moduleCode;
88
+ const moduleCode = input.moduleCode;
75
89
  const { vfModules, relative } = findNestedImports(moduleCode);
76
90
  input.log?.debug(`${LOG_PREFIX_MDX_LOADER} [fetchAndCacheModule] found nested imports`, {
77
91
  projectSlug: input.projectSlug,
@@ -87,32 +101,26 @@ export async function resolveNestedModuleImports(input) {
87
101
  count: vfModules.length,
88
102
  });
89
103
  const vfStart = performance.now();
90
- const nestedResults = await Promise.all(vfModules.map(async ({ original, path }) => ({
104
+ const allImports = [
105
+ ...vfModules.map((module) => ({ ...module, key: "nestedPath" })),
106
+ ...relative.map((module) => ({ ...module, key: "relativePath" })),
107
+ ];
108
+ const nestedResults = await Promise.all(allImports.map(async ({ original, path, start, end, key }) => ({
91
109
  original,
110
+ start,
111
+ end,
92
112
  nestedFilePath: await input.fetchAndCacheModule(path, input.normalizedPath),
93
- nestedPath: path,
113
+ [key]: path,
94
114
  })));
95
115
  input.log?.debug(`${LOG_PREFIX_MDX_LOADER} [fetchAndCacheModule] processing vfModules DONE`, {
96
116
  projectSlug: input.projectSlug,
97
117
  normalizedPath: input.normalizedPath,
98
118
  vfMs: (performance.now() - vfStart).toFixed(1),
99
119
  });
100
- moduleCode = await processNestedImports(moduleCode, nestedResults, input.esmCacheDir, input.strictMissingModules, input.normalizedPath, input.projectSlug);
101
- input.log?.debug(`${LOG_PREFIX_MDX_LOADER} [fetchAndCacheModule] processing relative imports START`, {
120
+ input.log?.debug(`${LOG_PREFIX_MDX_LOADER} [fetchAndCacheModule] processing relative imports`, {
102
121
  projectSlug: input.projectSlug,
103
122
  normalizedPath: input.normalizedPath,
104
123
  count: relative.length,
105
124
  });
106
- const relStart = performance.now();
107
- const relativeResults = await Promise.all(relative.map(async ({ original, path }) => ({
108
- original,
109
- nestedFilePath: await input.fetchAndCacheModule(path, input.normalizedPath),
110
- relativePath: path,
111
- })));
112
- input.log?.debug(`${LOG_PREFIX_MDX_LOADER} [fetchAndCacheModule] processing relative imports DONE`, {
113
- projectSlug: input.projectSlug,
114
- normalizedPath: input.normalizedPath,
115
- relMs: (performance.now() - relStart).toFixed(1),
116
- });
117
- return await processNestedImports(moduleCode, relativeResults, input.esmCacheDir, input.strictMissingModules, input.normalizedPath, input.projectSlug);
125
+ return await processNestedImports(moduleCode, nestedResults, input.esmCacheDir, input.strictMissingModules, input.normalizedPath, input.projectSlug);
118
126
  }
@@ -5,6 +5,11 @@
5
5
  *
6
6
  * @module transforms/mdx/esm-module-loader/module-fetcher/render-sessions
7
7
  */
8
+ /**
9
+ * Run `fn` with `sessionId` bound as the active render session for all async
10
+ * work it spawns. Modules fetched inside are attributed to this session.
11
+ */
12
+ export declare function runInRenderSession<T>(sessionId: string, fn: () => T): T;
8
13
  /**
9
14
  * Start a render session to track module loading.
10
15
  * Call this before rendering a page.
@@ -1 +1 @@
1
- {"version":3,"file":"render-sessions.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/render-sessions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqBH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAOhG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAiCxD;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE3D;AAWD,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAQlE"}
1
+ {"version":3,"file":"render-sessions.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/mdx/esm-module-loader/module-fetcher/render-sessions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA6BH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEvE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAOhG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAiCxD;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE3D;AAuBD,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAQlE"}
@@ -5,6 +5,7 @@
5
5
  *
6
6
  * @module transforms/mdx/esm-module-loader/module-fetcher/render-sessions
7
7
  */
8
+ import { AsyncLocalStorage } from "node:async_hooks";
8
9
  import { rendererLogger as globalLogger } from "../../../../utils/index.js";
9
10
  import { LOG_PREFIX_MDX_LOADER } from "../constants.js";
10
11
  import { recordSSRModules } from "../../../../modules/manifest/route-module-manifest.js";
@@ -13,6 +14,19 @@ import { recordSSRModules } from "../../../../modules/manifest/route-module-mani
13
14
  * Key: renderSessionId, Value: RenderSession
14
15
  */
15
16
  const renderSessions = new Map();
17
+ /**
18
+ * The render session id active on the current async execution context.
19
+ * Set via {@link runInRenderSession} so concurrent SSR renders each resolve
20
+ * their own session instead of sharing whichever one started first.
21
+ */
22
+ const currentSessionIdStorage = new AsyncLocalStorage();
23
+ /**
24
+ * Run `fn` with `sessionId` bound as the active render session for all async
25
+ * work it spawns. Modules fetched inside are attributed to this session.
26
+ */
27
+ export function runInRenderSession(sessionId, fn) {
28
+ return currentSessionIdStorage.run(sessionId, fn);
29
+ }
16
30
  /**
17
31
  * Start a render session to track module loading.
18
32
  * Call this before rendering a page.
@@ -66,8 +80,19 @@ export function hasRenderSession(sessionId) {
66
80
  * Used to record modules during fetch and for per-session in-flight deduplication.
67
81
  */
68
82
  function getCurrentSession() {
69
- const firstSession = renderSessions.values().next();
70
- return firstSession.done ? null : firstSession.value;
83
+ const activeId = currentSessionIdStorage.getStore();
84
+ if (activeId !== undefined) {
85
+ return renderSessions.get(activeId) ?? null;
86
+ }
87
+ // No session bound on the async context (caller not wrapped in
88
+ // runInRenderSession). Fall back to the single-session heuristic only when
89
+ // it is unambiguous; with multiple concurrent sessions, decline rather than
90
+ // mis-attribute modules to the wrong render.
91
+ if (renderSessions.size === 1) {
92
+ const firstSession = renderSessions.values().next();
93
+ return firstSession.done ? null : firstSession.value;
94
+ }
95
+ return null;
71
96
  }
72
97
  export function recordModuleToSession(normalizedPath) {
73
98
  const session = getCurrentSession();