remote-components 0.3.3 → 0.3.5

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 (176) hide show
  1. package/dist/config/nextjs.cjs +86 -37
  2. package/dist/config/nextjs.cjs.map +1 -1
  3. package/dist/config/nextjs.js +86 -37
  4. package/dist/config/nextjs.js.map +1 -1
  5. package/dist/config/webpack.cjs +5 -1
  6. package/dist/config/webpack.cjs.map +1 -1
  7. package/dist/config/webpack.js +5 -1
  8. package/dist/config/webpack.js.map +1 -1
  9. package/dist/host/html.cjs +861 -617
  10. package/dist/host/html.cjs.map +1 -1
  11. package/dist/host/html.js +861 -617
  12. package/dist/host/html.js.map +1 -1
  13. package/dist/host/nextjs/app/client-only.cjs +700 -383
  14. package/dist/host/nextjs/app/client-only.cjs.map +1 -1
  15. package/dist/host/nextjs/app/client-only.js +674 -357
  16. package/dist/host/nextjs/app/client-only.js.map +1 -1
  17. package/dist/host/nextjs/app.cjs +34 -2
  18. package/dist/host/nextjs/app.cjs.map +1 -1
  19. package/dist/host/nextjs/app.js +35 -3
  20. package/dist/host/nextjs/app.js.map +1 -1
  21. package/dist/host/react.cjs +641 -352
  22. package/dist/host/react.cjs.map +1 -1
  23. package/dist/host/react.js +641 -352
  24. package/dist/host/react.js.map +1 -1
  25. package/dist/internal/config/webpack/apply-shared-modules.cjs +6 -4
  26. package/dist/internal/config/webpack/apply-shared-modules.cjs.map +1 -1
  27. package/dist/internal/config/webpack/apply-shared-modules.js +6 -4
  28. package/dist/internal/config/webpack/apply-shared-modules.js.map +1 -1
  29. package/dist/internal/config/webpack/next-client-pages-loader.cjs +6 -7
  30. package/dist/internal/config/webpack/next-client-pages-loader.cjs.map +1 -1
  31. package/dist/internal/config/webpack/next-client-pages-loader.js +6 -7
  32. package/dist/internal/config/webpack/next-client-pages-loader.js.map +1 -1
  33. package/dist/internal/host/nextjs/app-client.cjs +42 -27
  34. package/dist/internal/host/nextjs/app-client.cjs.map +1 -1
  35. package/dist/internal/host/nextjs/app-client.js +42 -27
  36. package/dist/internal/host/nextjs/app-client.js.map +1 -1
  37. package/dist/internal/host/nextjs/dom-flight.cjs +19 -39
  38. package/dist/internal/host/nextjs/dom-flight.cjs.map +1 -1
  39. package/dist/internal/host/nextjs/dom-flight.js +31 -39
  40. package/dist/internal/host/nextjs/dom-flight.js.map +1 -1
  41. package/dist/internal/host/nextjs/image-shared.cjs +39 -3
  42. package/dist/internal/host/nextjs/image-shared.cjs.map +1 -1
  43. package/dist/internal/host/nextjs/image-shared.d.ts +5 -10
  44. package/dist/internal/host/nextjs/image-shared.js +29 -3
  45. package/dist/internal/host/nextjs/image-shared.js.map +1 -1
  46. package/dist/internal/host/nextjs/remote-component-links.cjs +24 -13
  47. package/dist/internal/host/nextjs/remote-component-links.cjs.map +1 -1
  48. package/dist/internal/host/nextjs/remote-component-links.d.ts +3 -0
  49. package/dist/internal/host/nextjs/remote-component-links.js +24 -13
  50. package/dist/internal/host/nextjs/remote-component-links.js.map +1 -1
  51. package/dist/internal/host/server/fetch-remote-component.cjs +2 -1
  52. package/dist/internal/host/server/fetch-remote-component.cjs.map +1 -1
  53. package/dist/internal/host/server/fetch-remote-component.js +2 -1
  54. package/dist/internal/host/server/fetch-remote-component.js.map +1 -1
  55. package/dist/internal/host/shared/lifecycle.cjs +69 -0
  56. package/dist/internal/host/shared/lifecycle.cjs.map +1 -0
  57. package/dist/internal/host/shared/lifecycle.d.ts +34 -0
  58. package/dist/internal/host/shared/lifecycle.js +44 -0
  59. package/dist/internal/host/shared/lifecycle.js.map +1 -0
  60. package/dist/internal/host/shared/pipeline.cjs +222 -0
  61. package/dist/internal/host/shared/pipeline.cjs.map +1 -0
  62. package/dist/internal/host/shared/pipeline.d.ts +153 -0
  63. package/dist/internal/host/shared/pipeline.js +200 -0
  64. package/dist/internal/host/shared/pipeline.js.map +1 -0
  65. package/dist/internal/host/shared/polyfill.cjs +8 -7
  66. package/dist/internal/host/shared/polyfill.cjs.map +1 -1
  67. package/dist/internal/host/shared/polyfill.js +8 -7
  68. package/dist/internal/host/shared/polyfill.js.map +1 -1
  69. package/dist/internal/host/shared/shared-module-resolver.cjs +117 -0
  70. package/dist/internal/host/shared/shared-module-resolver.cjs.map +1 -0
  71. package/dist/internal/host/shared/shared-module-resolver.d.ts +64 -0
  72. package/dist/internal/host/shared/shared-module-resolver.js +78 -0
  73. package/dist/internal/host/shared/shared-module-resolver.js.map +1 -0
  74. package/dist/internal/remote/nextjs/next-internals.cjs +53 -0
  75. package/dist/internal/remote/nextjs/next-internals.cjs.map +1 -0
  76. package/dist/internal/remote/nextjs/next-internals.d.ts +42 -0
  77. package/dist/internal/remote/nextjs/next-internals.js +26 -0
  78. package/dist/internal/remote/nextjs/next-internals.js.map +1 -0
  79. package/dist/internal/runtime/html/apply-origin.cjs +11 -32
  80. package/dist/internal/runtime/html/apply-origin.cjs.map +1 -1
  81. package/dist/internal/runtime/html/apply-origin.js +11 -32
  82. package/dist/internal/runtime/html/apply-origin.js.map +1 -1
  83. package/dist/internal/runtime/html/html-spec.cjs +78 -0
  84. package/dist/internal/runtime/html/html-spec.cjs.map +1 -0
  85. package/dist/internal/runtime/html/html-spec.d.ts +23 -0
  86. package/dist/internal/runtime/html/html-spec.js +41 -0
  87. package/dist/internal/runtime/html/html-spec.js.map +1 -0
  88. package/dist/internal/runtime/html/parse-remote-html.cjs +15 -12
  89. package/dist/internal/runtime/html/parse-remote-html.cjs.map +1 -1
  90. package/dist/internal/runtime/html/parse-remote-html.js +29 -12
  91. package/dist/internal/runtime/html/parse-remote-html.js.map +1 -1
  92. package/dist/internal/runtime/html/rewrite-srcset.cjs +38 -0
  93. package/dist/internal/runtime/html/rewrite-srcset.cjs.map +1 -0
  94. package/dist/internal/runtime/html/rewrite-srcset.d.ts +12 -0
  95. package/dist/internal/runtime/html/rewrite-srcset.js +14 -0
  96. package/dist/internal/runtime/html/rewrite-srcset.js.map +1 -0
  97. package/dist/internal/runtime/loaders/component-loader.cjs +25 -44
  98. package/dist/internal/runtime/loaders/component-loader.cjs.map +1 -1
  99. package/dist/internal/runtime/loaders/component-loader.d.ts +3 -1
  100. package/dist/internal/runtime/loaders/component-loader.js +28 -44
  101. package/dist/internal/runtime/loaders/component-loader.js.map +1 -1
  102. package/dist/internal/runtime/loaders/static-loader.cjs +15 -21
  103. package/dist/internal/runtime/loaders/static-loader.cjs.map +1 -1
  104. package/dist/internal/runtime/loaders/static-loader.d.ts +3 -1
  105. package/dist/internal/runtime/loaders/static-loader.js +15 -21
  106. package/dist/internal/runtime/loaders/static-loader.js.map +1 -1
  107. package/dist/internal/runtime/namespace.cjs +82 -0
  108. package/dist/internal/runtime/namespace.cjs.map +1 -0
  109. package/dist/internal/runtime/namespace.d.ts +5 -0
  110. package/dist/internal/runtime/namespace.js +58 -0
  111. package/dist/internal/runtime/namespace.js.map +1 -0
  112. package/dist/internal/runtime/rsc-imports.cjs +86 -0
  113. package/dist/internal/runtime/rsc-imports.cjs.map +1 -0
  114. package/dist/internal/runtime/rsc-imports.d.ts +39 -0
  115. package/dist/internal/runtime/rsc-imports.js +50 -0
  116. package/dist/internal/runtime/rsc-imports.js.map +1 -0
  117. package/dist/internal/runtime/rsc-runtime.cjs +17 -0
  118. package/dist/internal/runtime/rsc-runtime.cjs.map +1 -0
  119. package/dist/internal/runtime/rsc-runtime.d.ts +37 -0
  120. package/dist/internal/runtime/rsc-runtime.js +1 -0
  121. package/dist/internal/runtime/rsc-runtime.js.map +1 -0
  122. package/dist/internal/runtime/rsc.cjs +23 -12
  123. package/dist/internal/runtime/rsc.cjs.map +1 -1
  124. package/dist/internal/runtime/rsc.d.ts +19 -2
  125. package/dist/internal/runtime/rsc.js +20 -11
  126. package/dist/internal/runtime/rsc.js.map +1 -1
  127. package/dist/internal/runtime/turbopack/chunk-loader.cjs +53 -35
  128. package/dist/internal/runtime/turbopack/chunk-loader.cjs.map +1 -1
  129. package/dist/internal/runtime/turbopack/chunk-loader.d.ts +1 -1
  130. package/dist/internal/runtime/turbopack/chunk-loader.js +53 -35
  131. package/dist/internal/runtime/turbopack/chunk-loader.js.map +1 -1
  132. package/dist/internal/runtime/turbopack/module.cjs +17 -4
  133. package/dist/internal/runtime/turbopack/module.cjs.map +1 -1
  134. package/dist/internal/runtime/turbopack/module.d.ts +23 -1
  135. package/dist/internal/runtime/turbopack/module.js +16 -4
  136. package/dist/internal/runtime/turbopack/module.js.map +1 -1
  137. package/dist/internal/runtime/turbopack/patterns.cjs +26 -10
  138. package/dist/internal/runtime/turbopack/patterns.cjs.map +1 -1
  139. package/dist/internal/runtime/turbopack/patterns.d.ts +44 -49
  140. package/dist/internal/runtime/turbopack/patterns.js +23 -7
  141. package/dist/internal/runtime/turbopack/patterns.js.map +1 -1
  142. package/dist/internal/runtime/turbopack/{webpack-runtime.cjs → remote-scope-setup.cjs} +35 -32
  143. package/dist/internal/runtime/turbopack/remote-scope-setup.cjs.map +1 -0
  144. package/dist/internal/runtime/turbopack/remote-scope-setup.d.ts +25 -0
  145. package/dist/internal/runtime/turbopack/{webpack-runtime.js → remote-scope-setup.js} +36 -19
  146. package/dist/internal/runtime/turbopack/remote-scope-setup.js.map +1 -0
  147. package/dist/internal/runtime/turbopack/remote-scope.cjs +4 -6
  148. package/dist/internal/runtime/turbopack/remote-scope.cjs.map +1 -1
  149. package/dist/internal/runtime/turbopack/remote-scope.d.ts +20 -1
  150. package/dist/internal/runtime/turbopack/remote-scope.js +4 -6
  151. package/dist/internal/runtime/turbopack/remote-scope.js.map +1 -1
  152. package/dist/internal/runtime/turbopack/shared-modules.cjs +21 -15
  153. package/dist/internal/runtime/turbopack/shared-modules.cjs.map +1 -1
  154. package/dist/internal/runtime/turbopack/shared-modules.d.ts +9 -2
  155. package/dist/internal/runtime/turbopack/shared-modules.js +24 -18
  156. package/dist/internal/runtime/turbopack/shared-modules.js.map +1 -1
  157. package/dist/internal/runtime/types.cjs.map +1 -1
  158. package/dist/internal/runtime/types.d.ts +5 -41
  159. package/dist/internal/utils/logger.cjs +1 -1
  160. package/dist/internal/utils/logger.cjs.map +1 -1
  161. package/dist/internal/utils/logger.d.ts +2 -2
  162. package/dist/internal/utils/logger.js +1 -1
  163. package/dist/internal/utils/logger.js.map +1 -1
  164. package/dist/remote/html.cjs +78 -22
  165. package/dist/remote/html.cjs.map +1 -1
  166. package/dist/remote/html.js +78 -22
  167. package/dist/remote/html.js.map +1 -1
  168. package/dist/remote/nextjs/app.cjs +14 -55
  169. package/dist/remote/nextjs/app.cjs.map +1 -1
  170. package/dist/remote/nextjs/app.js +24 -45
  171. package/dist/remote/nextjs/app.js.map +1 -1
  172. package/dist/types-59251814.d.ts +94 -0
  173. package/package.json +2 -2
  174. package/dist/internal/runtime/turbopack/webpack-runtime.cjs.map +0 -1
  175. package/dist/internal/runtime/turbopack/webpack-runtime.d.ts +0 -23
  176. package/dist/internal/runtime/turbopack/webpack-runtime.js.map +0 -1
@@ -2,27 +2,48 @@ import {
2
2
  RUNTIME_TURBOPACK,
3
3
  RUNTIME_WEBPACK
4
4
  } from "#internal/runtime/constants";
5
+ import { getNamespace } from "#internal/runtime/namespace";
5
6
  import { REMOTE_COMPONENT_REGEX } from "#internal/runtime/patterns";
6
7
  import { RemoteComponentsError } from "#internal/utils/error";
7
8
  import { logDebug, logWarn } from "#internal/utils/logger";
8
9
  import { createChunkDispatcher, loadChunkWithScope } from "./chunk-loader";
9
10
  import { requireModule } from "./module";
10
- import { createScope, getScope, registerScope } from "./remote-scope";
11
- import { initializeSharedModules } from "./shared-modules";
12
- async function setupWebpackRuntime(runtime, scripts = [], url = new URL(location.href), bundle, shared = {}, remoteShared = {}, resolveClientUrl) {
11
+ import {
12
+ createScope,
13
+ getScope,
14
+ registerScope
15
+ } from "./remote-scope";
16
+ async function setupRemoteScope(runtime, scripts = [], url = new URL(location.href), bundle, resolveClientUrl) {
13
17
  const self = globalThis;
18
+ const ns = getNamespace();
14
19
  const bundleName = bundle ?? "default";
20
+ const existingScope = getScope(bundleName);
21
+ if (existingScope && existingScope.url.origin === url.origin) {
22
+ logDebug(
23
+ "WebpackRuntime",
24
+ `Reusing scope "${existingScope.scopedName}" (turbopackModules=${existingScope.turbopackModules.length})`
25
+ );
26
+ existingScope.resolveClientUrl = resolveClientUrl;
27
+ if (runtime === RUNTIME_TURBOPACK) {
28
+ await Promise.allSettled(
29
+ scripts.map(
30
+ (script) => script.src ? loadChunkWithScope(existingScope, script.src) : Promise.resolve(void 0)
31
+ )
32
+ );
33
+ }
34
+ return existingScope;
35
+ }
15
36
  const scope = createScope(bundleName, url, runtime, resolveClientUrl);
16
37
  registerScope(scope);
17
- if (!self.__remote_bundle_url__) {
18
- self.__remote_bundle_url__ = {};
38
+ if (runtime === RUNTIME_WEBPACK && self.__remote_webpack_require__?.[bundleName]) {
39
+ scope.webpackRequire = self.__remote_webpack_require__[bundleName];
19
40
  }
20
- self.__remote_bundle_url__[bundleName] = url;
41
+ ns.bundleUrls[bundleName] = url;
21
42
  if (scope.scopedName !== bundleName) {
22
- self.__remote_bundle_url__[scope.scopedName] = url;
43
+ ns.bundleUrls[scope.scopedName] = url;
23
44
  }
24
45
  self.__webpack_get_script_filename__ = () => null;
25
- const willCreateDispatchers = typeof self.__webpack_require__ !== "function" || self.__webpack_require_type__ !== "turbopack";
46
+ const willCreateDispatchers = typeof self.__webpack_require__ !== "function" || ns.dispatcherRuntime !== "turbopack";
26
47
  if (willCreateDispatchers) {
27
48
  if (!self.__original_webpack_require__ && !self.__original_webpack_chunk_load__) {
28
49
  self.__original_webpack_chunk_load__ = self.__webpack_chunk_load__;
@@ -30,6 +51,7 @@ async function setupWebpackRuntime(runtime, scripts = [], url = new URL(location
30
51
  }
31
52
  self.__webpack_chunk_load__ = createChunkDispatcher();
32
53
  self.__webpack_require__ = createModuleDispatcher(runtime);
54
+ ns.dispatcherRuntime = runtime;
33
55
  self.__webpack_require_type__ = runtime;
34
56
  if (self.__remote_webpack_require__ && runtime === RUNTIME_TURBOPACK) {
35
57
  self.__remote_webpack_require__[bundleName] = self.__webpack_require__;
@@ -57,15 +79,7 @@ async function setupWebpackRuntime(runtime, scripts = [], url = new URL(location
57
79
  }
58
80
  }
59
81
  }
60
- const coreShared = {
61
- react: async () => (await import("react")).default,
62
- "react-dom": async () => (await import("react-dom")).default,
63
- "react/jsx-dev-runtime": async () => (await import("react/jsx-dev-runtime")).default,
64
- "react/jsx-runtime": async () => (await import("react/jsx-runtime")).default,
65
- "react-dom/client": async () => (await import("react-dom/client")).default,
66
- ...shared
67
- };
68
- await initializeSharedModules(scope, coreShared, remoteShared);
82
+ return scope;
69
83
  }
70
84
  function createModuleDispatcher(runtime) {
71
85
  return (id) => {
@@ -82,6 +96,9 @@ function createModuleDispatcher(runtime) {
82
96
  );
83
97
  try {
84
98
  if (remoteRuntime === RUNTIME_WEBPACK && bundle && moduleId) {
99
+ const scope2 = getScope(bundle);
100
+ if (scope2?.webpackRequire)
101
+ return scope2.webpackRequire(moduleId);
85
102
  return self.__remote_webpack_require__?.[bundle]?.(moduleId);
86
103
  }
87
104
  const scope = getScope(bundleName);
@@ -120,6 +137,6 @@ function createModuleDispatcher(runtime) {
120
137
  };
121
138
  }
122
139
  export {
123
- setupWebpackRuntime
140
+ setupRemoteScope
124
141
  };
125
- //# sourceMappingURL=webpack-runtime.js.map
142
+ //# sourceMappingURL=remote-scope-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/runtime/turbopack/remote-scope-setup.ts"],"sourcesContent":["import type { InternalResolveClientUrl } from '#internal/host/server/types';\nimport {\n RUNTIME_TURBOPACK,\n RUNTIME_WEBPACK,\n type Runtime,\n} from '#internal/runtime/constants';\nimport { getNamespace } from '#internal/runtime/namespace';\nimport { REMOTE_COMPONENT_REGEX } from '#internal/runtime/patterns';\nimport type { GlobalScope } from '#internal/runtime/types';\nimport { RemoteComponentsError } from '#internal/utils/error';\nimport { logDebug, logWarn } from '#internal/utils/logger';\nimport { createChunkDispatcher, loadChunkWithScope } from './chunk-loader';\nimport { requireModule } from './module';\nimport {\n createScope,\n getScope,\n type RemoteScope,\n registerScope,\n} from './remote-scope';\n\n/**\n * Sets up the bundler runtime environment for remote components.\n *\n * Creates a RemoteScope that encapsulates all per-remote state (base URL,\n * proxy callback, module cache, shared modules) and registers it in the\n * global scope registry. Global dispatchers (__webpack_require__,\n * __webpack_chunk_load__) are set once and route to the correct scope.\n *\n * Shared module initialization is NOT performed here — callers must invoke\n * `initializeSharedModules` separately after this function returns. This\n * separation ensures shared modules are initialized after turbopack chunks\n * are loaded (so the primary bundle-introspection path is used), avoiding\n * the fallback that keys shared modules by file path instead of numeric ID.\n *\n * @returns The scope (newly created or reused) for the bundle.\n */\nexport async function setupRemoteScope(\n runtime: Runtime,\n scripts: { src: string | null }[] = [],\n url: URL = new URL(location.href),\n bundle?: string,\n resolveClientUrl?: InternalResolveClientUrl,\n): Promise<RemoteScope> {\n const self = globalThis as GlobalScope;\n const ns = getNamespace();\n const bundleName = bundle ?? 'default';\n\n // When the same remote loads a second component (e.g. switching from basic\n // to styled), reuse the existing scope. The chunk cache is keyed by URL and\n // returns cached promises without re-running handleTurbopackChunk, so\n // turbopackModules, moduleCache, and sharedModules from the first load are\n // all still valid. Only resolveClientUrl may have changed.\n //\n // Origin-only comparison is sufficient because bundleName already identifies\n // a specific remote — different paths on the same origin would be a different\n // bundle with a different name, so getScope() wouldn't return a match.\n const existingScope = getScope(bundleName);\n if (existingScope && existingScope.url.origin === url.origin) {\n logDebug(\n 'WebpackRuntime',\n `Reusing scope \"${existingScope.scopedName}\" (turbopackModules=${existingScope.turbopackModules.length})`,\n );\n existingScope.resolveClientUrl = resolveClientUrl;\n\n // Still load scripts — chunk cache deduplicates already-loaded chunks,\n // and a different component may reference additional chunks.\n if (runtime === RUNTIME_TURBOPACK) {\n await Promise.allSettled(\n scripts.map((script) =>\n script.src\n ? loadChunkWithScope(existingScope, script.src)\n : Promise.resolve(undefined),\n ),\n );\n }\n return existingScope;\n }\n\n const scope = createScope(bundleName, url, runtime, resolveClientUrl);\n registerScope(scope);\n\n // For webpack remotes the remote's own scripts have already loaded (via\n // loadScripts in component-loader) and populated __remote_webpack_require__\n // under the plain bundle name. Capture the reference on the scope so\n // downstream code (applySharedModules, module dispatcher) can use it\n // without reaching into the global.\n if (\n runtime === RUNTIME_WEBPACK &&\n self.__remote_webpack_require__?.[bundleName]\n ) {\n scope.webpackRequire = self.__remote_webpack_require__[bundleName];\n }\n\n ns.bundleUrls[bundleName] = url;\n // Also register under scopedName so webpack hosts (patch-require.ts) can\n // resolve cross-origin remotes whose bundle identifiers were rewritten.\n if (scope.scopedName !== bundleName) {\n ns.bundleUrls[scope.scopedName] = url;\n }\n self.__webpack_get_script_filename__ = () => null;\n\n const willCreateDispatchers =\n typeof self.__webpack_require__ !== 'function' ||\n ns.dispatcherRuntime !== 'turbopack';\n\n if (willCreateDispatchers) {\n // preserve original webpack functions for fallback\n if (\n !self.__original_webpack_require__ &&\n !self.__original_webpack_chunk_load__\n ) {\n self.__original_webpack_chunk_load__ = self.__webpack_chunk_load__;\n self.__original_webpack_require__ = self.__webpack_require__;\n }\n\n self.__webpack_chunk_load__ = createChunkDispatcher();\n self.__webpack_require__ = createModuleDispatcher(runtime);\n // Write-through needed: dispatcherRuntime is a primitive string,\n // so the legacy global can't be aliased by reference in getNamespace().\n ns.dispatcherRuntime = runtime;\n self.__webpack_require_type__ = runtime;\n\n // @legacy(v0.3.4) — __remote_webpack_require__ write-through for turbopack remotes.\n // Needed by PatchRequirePlugin which reads this global at runtime.\n // Remove once PatchRequirePlugin reads from scope.\n if (self.__remote_webpack_require__ && runtime === RUNTIME_TURBOPACK) {\n self.__remote_webpack_require__[bundleName] =\n self.__webpack_require__ as (remoteId: string | number) => unknown;\n self.__remote_webpack_require__[bundleName].type = 'turbopack';\n }\n }\n\n // @legacy(v0.3.4) — __remote_webpack_require__ scoped-name alias.\n // Ensures PatchRequirePlugin can find webpack remotes under rewritten\n // bundle identifiers. Remove once PatchRequirePlugin reads from scope.\n if (\n self.__remote_webpack_require__?.[bundleName] &&\n scope.scopedName !== bundleName\n ) {\n self.__remote_webpack_require__[scope.scopedName] =\n self.__remote_webpack_require__[bundleName];\n }\n\n // load all initial chunks directly via scope — no global dispatch needed\n if (runtime === RUNTIME_TURBOPACK) {\n const results = await Promise.allSettled(\n scripts.map((script) => {\n if (script.src) {\n return loadChunkWithScope(scope, script.src);\n }\n return Promise.resolve(undefined);\n }),\n );\n\n for (const result of results) {\n if (result.status === 'rejected') {\n logWarn(\n 'WebpackRuntime',\n `Initial chunk load failed: ${String(result.reason)}`,\n );\n }\n }\n }\n\n return scope;\n}\n\n/**\n * Creates the global module dispatcher for __webpack_require__.\n * Called by external code (React's RSC runtime) that doesn't have access to\n * a scope. Parses the module ID to find the correct scope and delegates\n * to scope-local module resolution.\n */\nfunction createModuleDispatcher(runtime: Runtime): (id: string) => unknown {\n return (id: string) => {\n const self = globalThis as GlobalScope;\n const { bundle, id: moduleId } = id.match(REMOTE_COMPONENT_REGEX)\n ?.groups ?? {\n bundle: 'default',\n id,\n };\n const bundleName = bundle ?? 'default';\n const remoteRuntime = self.__remote_webpack_require__?.[bundleName]\n ? self.__remote_webpack_require__[bundleName]?.type || 'webpack'\n : runtime;\n\n logDebug(\n 'ModuleDispatcher',\n `Resolving \"${id}\" (bundle: \"${bundleName}\", runtime: \"${remoteRuntime}\")`,\n );\n\n try {\n // for webpack remotes, prefer scope-based dispatch then fall back to global\n if (remoteRuntime === RUNTIME_WEBPACK && bundle && moduleId) {\n const scope = getScope(bundle);\n if (scope?.webpackRequire) return scope.webpackRequire(moduleId);\n // @legacy(v0.3.4) — global fallback for hosts that populated\n // __remote_webpack_require__ without calling setupWebpackRuntime.\n return self.__remote_webpack_require__?.[bundle]?.(moduleId);\n }\n\n // Look up scope by parsed bundle name. Works with both the scoped\n // name (Next.js hosts with server-side rewriting) and the plain\n // bundle name (static/HTML hosts with unrewritten chunks).\n const scope = getScope(bundleName);\n if (scope) {\n return requireModule(scope, moduleId ?? id, id);\n }\n\n throw new Error(\n `Module \"${id}\" not found — no scope for bundle \"${bundleName}\".`,\n );\n } catch (requireError) {\n logWarn(\n 'ModuleDispatcher',\n `Module require failed: ${String(requireError)}`,\n );\n if (typeof self.__original_webpack_require__ !== 'function') {\n throw new RemoteComponentsError(\n `Module \"${id}\" not found in remote component bundle \"${bundleName}\".`,\n {\n cause: requireError instanceof Error ? requireError : undefined,\n },\n );\n }\n try {\n logDebug(\n 'ModuleDispatcher',\n 'Falling back to original webpack require',\n );\n return self.__original_webpack_require__(id);\n } catch (originalError) {\n throw new RemoteComponentsError(\n `Module \"${id}\" not found in remote component bundle \"${bundleName}\".`,\n { cause: originalError instanceof Error ? originalError : undefined },\n );\n }\n }\n };\n}\n"],"mappings":"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","names":["scope"]}
@@ -26,15 +26,12 @@ __export(remote_scope_exports, {
26
26
  });
27
27
  module.exports = __toCommonJS(remote_scope_exports);
28
28
  var import_constants = require("#internal/runtime/constants");
29
+ var import_namespace = require("#internal/runtime/namespace");
29
30
  var import_patterns = require("#internal/runtime/patterns");
30
31
  var import_utils = require("#internal/utils");
31
32
  var import_logger = require("#internal/utils/logger");
32
33
  function getRegistry() {
33
- const self = globalThis;
34
- if (!self.__remote_component_scopes__) {
35
- self.__remote_component_scopes__ = /* @__PURE__ */ new Map();
36
- }
37
- return self.__remote_component_scopes__;
34
+ return (0, import_namespace.getNamespace)().scopes;
38
35
  }
39
36
  function createScope(name, url, runtime, resolveClientUrl) {
40
37
  const isCrossOrigin = url.origin !== location.origin;
@@ -52,7 +49,8 @@ function createScope(name, url, runtime, resolveClientUrl) {
52
49
  resolveClientUrl,
53
50
  moduleCache: {},
54
51
  sharedModules: {},
55
- moduleGlobal: {}
52
+ moduleGlobal: {},
53
+ turbopackModules: []
56
54
  };
57
55
  }
58
56
  function registerScope(scope) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/runtime/turbopack/remote-scope.ts"],"sourcesContent":["import type { InternalResolveClientUrl } from '#internal/host/server/types';\nimport { getBundleKey, type Runtime } from '#internal/runtime/constants';\nimport { REMOTE_COMPONENT_REGEX } from '#internal/runtime/patterns';\nimport type { GlobalScope } from '#internal/runtime/types';\nimport { computeScopedName } from '#internal/utils';\nimport { logDebug, logWarn } from '#internal/utils/logger';\n\n/**\n * Encapsulates all per-remote state so that two remotes sharing the same\n * bundle name but served from different origins never collide.\n *\n * A scope is created once per `setupWebpackRuntime` call and threaded\n * directly through internal code paths (chunk loading, module resolution,\n * shared modules). Global dispatchers (`__webpack_require__`,\n * `__webpack_chunk_load__`) only exist for external callers (RSC runtime)\n * and resolve the correct scope via the registry.\n */\nexport interface RemoteScope {\n /** Plain bundle name (e.g. \"remote-component-registry\") */\n name: string;\n /** Origin-qualified key — unique even when two remotes share a name */\n scopedName: string;\n /** Escaped key used as suffix for TURBOPACK_ globals */\n globalKey: string;\n /** Base URL for resolving relative chunk paths */\n url: URL;\n /** Bundler runtime type */\n runtime: Runtime;\n /** Proxy callback for routing chunks through the host */\n resolveClientUrl?: InternalResolveClientUrl;\n /** Per-scope cache of executed Turbopack module exports */\n moduleCache: Record<string, unknown>;\n /** Per-scope shared modules provided by the host (React, etc.) */\n sharedModules: Record<string, unknown>;\n /** Per-scope globalThis substitute passed to module initializers as `g` */\n moduleGlobal: Record<string, unknown>;\n}\n\nfunction getRegistry(): Map<string, RemoteScope> {\n const self = globalThis as GlobalScope;\n if (!self.__remote_component_scopes__) {\n self.__remote_component_scopes__ = new Map<string, unknown>();\n }\n return self.__remote_component_scopes__ as unknown as Map<\n string,\n RemoteScope\n >;\n}\n\nexport function createScope(\n name: string,\n url: URL,\n runtime: Runtime,\n resolveClientUrl?: InternalResolveClientUrl,\n): RemoteScope {\n const isCrossOrigin = url.origin !== location.origin;\n const scopedName = computeScopedName(name, {\n remoteHost: url.host,\n isCrossOrigin,\n });\n const globalKey = getBundleKey(scopedName);\n return {\n name,\n scopedName,\n globalKey,\n url,\n runtime,\n resolveClientUrl,\n moduleCache: {},\n sharedModules: {},\n moduleGlobal: {},\n };\n}\n\nexport function registerScope(scope: RemoteScope): void {\n const registry = getRegistry();\n registry.set(scope.scopedName, scope);\n\n // Also register under the plain name so hosts without server-side RSC\n // rewriting (static/HTML hosts) can look up cross-origin scopes by\n // the bundle name that appears in unrewritten chunk/module IDs.\n if (scope.scopedName !== scope.name) {\n const existing = registry.get(scope.name);\n if (existing && existing.scopedName !== scope.scopedName) {\n logWarn(\n 'RemoteScope',\n `Plain name \"${scope.name}\" already registered by scope \"${existing.scopedName}\" — ` +\n `overwriting with \"${scope.scopedName}\". Static hosts will only resolve the latest one.`,\n );\n }\n registry.set(scope.name, scope);\n }\n\n logDebug(\n 'RemoteScope',\n `Registered scope \"${scope.scopedName}\" (${registry.size} total)`,\n );\n}\n\n/**\n * Resolves a scope by name. Accepts either the scoped name (used by Next.js\n * hosts that rewrite RSC data server-side) or the plain bundle name (used by\n * static/HTML hosts where chunks arrive unrewritten).\n */\nexport function getScope(name: string): RemoteScope | undefined {\n return getRegistry().get(name);\n}\n\n/** Formats a `[scopedName] path` string for use in chunk/module IDs. */\nexport function formatRemoteId(scope: RemoteScope, path: string): string {\n return `[${scope.scopedName}] ${path}`;\n}\n\n/**\n * Parses the `[bundle] path` format used in chunk/module IDs.\n * Uses REMOTE_COMPONENT_REGEX (the same pattern used by the module dispatcher\n * and script loader) so the two parsing paths can never diverge.\n */\nexport function parseRemoteId(id: string): {\n bundle: string;\n path: string;\n prefix: string;\n} {\n const groups = REMOTE_COMPONENT_REGEX.exec(id)?.groups;\n if (groups?.bundle && groups.id) {\n return {\n bundle: groups.bundle,\n path: groups.id,\n prefix: groups.prefix ?? '',\n };\n }\n return { bundle: 'default', path: id, prefix: '' };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,uBAA2C;AAC3C,sBAAuC;AAEvC,mBAAkC;AAClC,oBAAkC;AAiClC,SAAS,cAAwC;AAC/C,QAAM,OAAO;AACb,MAAI,CAAC,KAAK,6BAA6B;AACrC,SAAK,8BAA8B,oBAAI,IAAqB;AAAA,EAC9D;AACA,SAAO,KAAK;AAId;AAEO,SAAS,YACd,MACA,KACA,SACA,kBACa;AACb,QAAM,gBAAgB,IAAI,WAAW,SAAS;AAC9C,QAAM,iBAAa,gCAAkB,MAAM;AAAA,IACzC,YAAY,IAAI;AAAA,IAChB;AAAA,EACF,CAAC;AACD,QAAM,gBAAY,+BAAa,UAAU;AACzC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,CAAC;AAAA,IACd,eAAe,CAAC;AAAA,IAChB,cAAc,CAAC;AAAA,EACjB;AACF;AAEO,SAAS,cAAc,OAA0B;AACtD,QAAM,WAAW,YAAY;AAC7B,WAAS,IAAI,MAAM,YAAY,KAAK;AAKpC,MAAI,MAAM,eAAe,MAAM,MAAM;AACnC,UAAM,WAAW,SAAS,IAAI,MAAM,IAAI;AACxC,QAAI,YAAY,SAAS,eAAe,MAAM,YAAY;AACxD;AAAA,QACE;AAAA,QACA,eAAe,MAAM,sCAAsC,SAAS,wCAC7C,MAAM;AAAA,MAC/B;AAAA,IACF;AACA,aAAS,IAAI,MAAM,MAAM,KAAK;AAAA,EAChC;AAEA;AAAA,IACE;AAAA,IACA,qBAAqB,MAAM,gBAAgB,SAAS;AAAA,EACtD;AACF;AAOO,SAAS,SAAS,MAAuC;AAC9D,SAAO,YAAY,EAAE,IAAI,IAAI;AAC/B;AAGO,SAAS,eAAe,OAAoB,MAAsB;AACvE,SAAO,IAAI,MAAM,eAAe;AAClC;AAOO,SAAS,cAAc,IAI5B;AACA,QAAM,SAAS,uCAAuB,KAAK,EAAE,GAAG;AAChD,MAAI,QAAQ,UAAU,OAAO,IAAI;AAC/B,WAAO;AAAA,MACL,QAAQ,OAAO;AAAA,MACf,MAAM,OAAO;AAAA,MACb,QAAQ,OAAO,UAAU;AAAA,IAC3B;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,WAAW,MAAM,IAAI,QAAQ,GAAG;AACnD;","names":[]}
1
+ {"version":3,"sources":["../../../../src/runtime/turbopack/remote-scope.ts"],"sourcesContent":["import type { InternalResolveClientUrl } from '#internal/host/server/types';\nimport { getBundleKey, type Runtime } from '#internal/runtime/constants';\nimport { getNamespace } from '#internal/runtime/namespace';\nimport { REMOTE_COMPONENT_REGEX } from '#internal/runtime/patterns';\nimport { computeScopedName } from '#internal/utils';\nimport { logDebug, logWarn } from '#internal/utils/logger';\n\n/**\n * Encapsulates all per-remote state so that two remotes sharing the same\n * bundle name but served from different origins never collide.\n *\n * A scope is created once per `setupRemoteScope` call and threaded\n * directly through internal code paths (chunk loading, module resolution,\n * shared modules). Global dispatchers (`__webpack_require__`,\n * `__webpack_chunk_load__`) only exist for external callers (RSC runtime)\n * and resolve the correct scope via the registry.\n */\nexport interface RemoteScope {\n /** Plain bundle name (e.g. \"remote-component-registry\") */\n name: string;\n /** Origin-qualified key — unique even when two remotes share a name */\n scopedName: string;\n /** Escaped key used as suffix for TURBOPACK_ globals */\n globalKey: string;\n /** Base URL for resolving relative chunk paths */\n url: URL;\n /** Bundler runtime type */\n runtime: Runtime;\n /** Proxy callback for routing chunks through the host */\n resolveClientUrl?: InternalResolveClientUrl;\n /** Per-scope cache of executed Turbopack module exports */\n moduleCache: Record<string, unknown>;\n /** Per-scope shared modules provided by the host (React, etc.) */\n sharedModules: Record<string, unknown>;\n /** Per-scope globalThis substitute passed to module initializers as `g` */\n moduleGlobal: Record<string, unknown>;\n /**\n * Webpack's bundle-scoped require function, populated from\n * `__remote_webpack_require__[bundleName]` for webpack remotes.\n * Undefined for turbopack remotes.\n */\n webpackRequire?: ((id: string | number) => unknown) & {\n m?: Record<string | number, (module: { exports: unknown }) => void>;\n type?: string;\n };\n /**\n * Flat array of captured turbopack module entries: [scriptEl, id, factory, ...].\n * Populated by the push interceptor in handleTurbopackChunk. This is the\n * primary source of truth for getTurbopackModules — immune to the turbopack\n * runtime replacing the TURBOPACK global (canary builds use a deferred-loading\n * pattern that swaps the array for an immediate-processing dispatcher).\n */\n turbopackModules: unknown[];\n}\n\nfunction getRegistry(): Map<string, RemoteScope> {\n return getNamespace().scopes;\n}\n\nexport function createScope(\n name: string,\n url: URL,\n runtime: Runtime,\n resolveClientUrl?: InternalResolveClientUrl,\n): RemoteScope {\n const isCrossOrigin = url.origin !== location.origin;\n const scopedName = computeScopedName(name, {\n remoteHost: url.host,\n isCrossOrigin,\n });\n const globalKey = getBundleKey(scopedName);\n return {\n name,\n scopedName,\n globalKey,\n url,\n runtime,\n resolveClientUrl,\n moduleCache: {},\n sharedModules: {},\n moduleGlobal: {},\n turbopackModules: [],\n };\n}\n\nexport function registerScope(scope: RemoteScope): void {\n const registry = getRegistry();\n registry.set(scope.scopedName, scope);\n\n // Also register under the plain name so hosts without server-side RSC\n // rewriting (static/HTML hosts) can look up cross-origin scopes by\n // the bundle name that appears in unrewritten chunk/module IDs.\n if (scope.scopedName !== scope.name) {\n const existing = registry.get(scope.name);\n if (existing && existing.scopedName !== scope.scopedName) {\n logWarn(\n 'RemoteScope',\n `Plain name \"${scope.name}\" already registered by scope \"${existing.scopedName}\" — ` +\n `overwriting with \"${scope.scopedName}\". Static hosts will only resolve the latest one.`,\n );\n }\n registry.set(scope.name, scope);\n }\n\n logDebug(\n 'RemoteScope',\n `Registered scope \"${scope.scopedName}\" (${registry.size} total)`,\n );\n}\n\n/**\n * Resolves a scope by name. Accepts either the scoped name (used by Next.js\n * hosts that rewrite RSC data server-side) or the plain bundle name (used by\n * static/HTML hosts where chunks arrive unrewritten).\n */\nexport function getScope(name: string): RemoteScope | undefined {\n return getRegistry().get(name);\n}\n\n/** Formats a `[scopedName] path` string for use in chunk/module IDs. */\nexport function formatRemoteId(scope: RemoteScope, path: string): string {\n return `[${scope.scopedName}] ${path}`;\n}\n\n/**\n * Parses the `[bundle] path` format used in chunk/module IDs.\n * Uses REMOTE_COMPONENT_REGEX (the same pattern used by the module dispatcher\n * and script loader) so the two parsing paths can never diverge.\n */\nexport function parseRemoteId(id: string): {\n bundle: string;\n path: string;\n prefix: string;\n} {\n const groups = REMOTE_COMPONENT_REGEX.exec(id)?.groups;\n if (groups?.bundle && groups.id) {\n return {\n bundle: groups.bundle,\n path: groups.id,\n prefix: groups.prefix ?? '',\n };\n }\n return { bundle: 'default', path: id, prefix: '' };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,uBAA2C;AAC3C,uBAA6B;AAC7B,sBAAuC;AACvC,mBAAkC;AAClC,oBAAkC;AAkDlC,SAAS,cAAwC;AAC/C,aAAO,+BAAa,EAAE;AACxB;AAEO,SAAS,YACd,MACA,KACA,SACA,kBACa;AACb,QAAM,gBAAgB,IAAI,WAAW,SAAS;AAC9C,QAAM,iBAAa,gCAAkB,MAAM;AAAA,IACzC,YAAY,IAAI;AAAA,IAChB;AAAA,EACF,CAAC;AACD,QAAM,gBAAY,+BAAa,UAAU;AACzC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,CAAC;AAAA,IACd,eAAe,CAAC;AAAA,IAChB,cAAc,CAAC;AAAA,IACf,kBAAkB,CAAC;AAAA,EACrB;AACF;AAEO,SAAS,cAAc,OAA0B;AACtD,QAAM,WAAW,YAAY;AAC7B,WAAS,IAAI,MAAM,YAAY,KAAK;AAKpC,MAAI,MAAM,eAAe,MAAM,MAAM;AACnC,UAAM,WAAW,SAAS,IAAI,MAAM,IAAI;AACxC,QAAI,YAAY,SAAS,eAAe,MAAM,YAAY;AACxD;AAAA,QACE;AAAA,QACA,eAAe,MAAM,sCAAsC,SAAS,wCAC7C,MAAM;AAAA,MAC/B;AAAA,IACF;AACA,aAAS,IAAI,MAAM,MAAM,KAAK;AAAA,EAChC;AAEA;AAAA,IACE;AAAA,IACA,qBAAqB,MAAM,gBAAgB,SAAS;AAAA,EACtD;AACF;AAOO,SAAS,SAAS,MAAuC;AAC9D,SAAO,YAAY,EAAE,IAAI,IAAI;AAC/B;AAGO,SAAS,eAAe,OAAoB,MAAsB;AACvE,SAAO,IAAI,MAAM,eAAe;AAClC;AAOO,SAAS,cAAc,IAI5B;AACA,QAAM,SAAS,uCAAuB,KAAK,EAAE,GAAG;AAChD,MAAI,QAAQ,UAAU,OAAO,IAAI;AAC/B,WAAO;AAAA,MACL,QAAQ,OAAO;AAAA,MACf,MAAM,OAAO;AAAA,MACb,QAAQ,OAAO,UAAU;AAAA,IAC3B;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,WAAW,MAAM,IAAI,QAAQ,GAAG;AACnD;","names":[]}
@@ -5,7 +5,7 @@ import { Runtime } from '../constants.js';
5
5
  * Encapsulates all per-remote state so that two remotes sharing the same
6
6
  * bundle name but served from different origins never collide.
7
7
  *
8
- * A scope is created once per `setupWebpackRuntime` call and threaded
8
+ * A scope is created once per `setupRemoteScope` call and threaded
9
9
  * directly through internal code paths (chunk loading, module resolution,
10
10
  * shared modules). Global dispatchers (`__webpack_require__`,
11
11
  * `__webpack_chunk_load__`) only exist for external callers (RSC runtime)
@@ -30,6 +30,25 @@ interface RemoteScope {
30
30
  sharedModules: Record<string, unknown>;
31
31
  /** Per-scope globalThis substitute passed to module initializers as `g` */
32
32
  moduleGlobal: Record<string, unknown>;
33
+ /**
34
+ * Webpack's bundle-scoped require function, populated from
35
+ * `__remote_webpack_require__[bundleName]` for webpack remotes.
36
+ * Undefined for turbopack remotes.
37
+ */
38
+ webpackRequire?: ((id: string | number) => unknown) & {
39
+ m?: Record<string | number, (module: {
40
+ exports: unknown;
41
+ }) => void>;
42
+ type?: string;
43
+ };
44
+ /**
45
+ * Flat array of captured turbopack module entries: [scriptEl, id, factory, ...].
46
+ * Populated by the push interceptor in handleTurbopackChunk. This is the
47
+ * primary source of truth for getTurbopackModules — immune to the turbopack
48
+ * runtime replacing the TURBOPACK global (canary builds use a deferred-loading
49
+ * pattern that swaps the array for an immediate-processing dispatcher).
50
+ */
51
+ turbopackModules: unknown[];
33
52
  }
34
53
  declare function createScope(name: string, url: URL, runtime: Runtime, resolveClientUrl?: InternalResolveClientUrl): RemoteScope;
35
54
  declare function registerScope(scope: RemoteScope): void;
@@ -1,13 +1,10 @@
1
1
  import { getBundleKey } from "#internal/runtime/constants";
2
+ import { getNamespace } from "#internal/runtime/namespace";
2
3
  import { REMOTE_COMPONENT_REGEX } from "#internal/runtime/patterns";
3
4
  import { computeScopedName } from "#internal/utils";
4
5
  import { logDebug, logWarn } from "#internal/utils/logger";
5
6
  function getRegistry() {
6
- const self = globalThis;
7
- if (!self.__remote_component_scopes__) {
8
- self.__remote_component_scopes__ = /* @__PURE__ */ new Map();
9
- }
10
- return self.__remote_component_scopes__;
7
+ return getNamespace().scopes;
11
8
  }
12
9
  function createScope(name, url, runtime, resolveClientUrl) {
13
10
  const isCrossOrigin = url.origin !== location.origin;
@@ -25,7 +22,8 @@ function createScope(name, url, runtime, resolveClientUrl) {
25
22
  resolveClientUrl,
26
23
  moduleCache: {},
27
24
  sharedModules: {},
28
- moduleGlobal: {}
25
+ moduleGlobal: {},
26
+ turbopackModules: []
29
27
  };
30
28
  }
31
29
  function registerScope(scope) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/runtime/turbopack/remote-scope.ts"],"sourcesContent":["import type { InternalResolveClientUrl } from '#internal/host/server/types';\nimport { getBundleKey, type Runtime } from '#internal/runtime/constants';\nimport { REMOTE_COMPONENT_REGEX } from '#internal/runtime/patterns';\nimport type { GlobalScope } from '#internal/runtime/types';\nimport { computeScopedName } from '#internal/utils';\nimport { logDebug, logWarn } from '#internal/utils/logger';\n\n/**\n * Encapsulates all per-remote state so that two remotes sharing the same\n * bundle name but served from different origins never collide.\n *\n * A scope is created once per `setupWebpackRuntime` call and threaded\n * directly through internal code paths (chunk loading, module resolution,\n * shared modules). Global dispatchers (`__webpack_require__`,\n * `__webpack_chunk_load__`) only exist for external callers (RSC runtime)\n * and resolve the correct scope via the registry.\n */\nexport interface RemoteScope {\n /** Plain bundle name (e.g. \"remote-component-registry\") */\n name: string;\n /** Origin-qualified key — unique even when two remotes share a name */\n scopedName: string;\n /** Escaped key used as suffix for TURBOPACK_ globals */\n globalKey: string;\n /** Base URL for resolving relative chunk paths */\n url: URL;\n /** Bundler runtime type */\n runtime: Runtime;\n /** Proxy callback for routing chunks through the host */\n resolveClientUrl?: InternalResolveClientUrl;\n /** Per-scope cache of executed Turbopack module exports */\n moduleCache: Record<string, unknown>;\n /** Per-scope shared modules provided by the host (React, etc.) */\n sharedModules: Record<string, unknown>;\n /** Per-scope globalThis substitute passed to module initializers as `g` */\n moduleGlobal: Record<string, unknown>;\n}\n\nfunction getRegistry(): Map<string, RemoteScope> {\n const self = globalThis as GlobalScope;\n if (!self.__remote_component_scopes__) {\n self.__remote_component_scopes__ = new Map<string, unknown>();\n }\n return self.__remote_component_scopes__ as unknown as Map<\n string,\n RemoteScope\n >;\n}\n\nexport function createScope(\n name: string,\n url: URL,\n runtime: Runtime,\n resolveClientUrl?: InternalResolveClientUrl,\n): RemoteScope {\n const isCrossOrigin = url.origin !== location.origin;\n const scopedName = computeScopedName(name, {\n remoteHost: url.host,\n isCrossOrigin,\n });\n const globalKey = getBundleKey(scopedName);\n return {\n name,\n scopedName,\n globalKey,\n url,\n runtime,\n resolveClientUrl,\n moduleCache: {},\n sharedModules: {},\n moduleGlobal: {},\n };\n}\n\nexport function registerScope(scope: RemoteScope): void {\n const registry = getRegistry();\n registry.set(scope.scopedName, scope);\n\n // Also register under the plain name so hosts without server-side RSC\n // rewriting (static/HTML hosts) can look up cross-origin scopes by\n // the bundle name that appears in unrewritten chunk/module IDs.\n if (scope.scopedName !== scope.name) {\n const existing = registry.get(scope.name);\n if (existing && existing.scopedName !== scope.scopedName) {\n logWarn(\n 'RemoteScope',\n `Plain name \"${scope.name}\" already registered by scope \"${existing.scopedName}\" — ` +\n `overwriting with \"${scope.scopedName}\". Static hosts will only resolve the latest one.`,\n );\n }\n registry.set(scope.name, scope);\n }\n\n logDebug(\n 'RemoteScope',\n `Registered scope \"${scope.scopedName}\" (${registry.size} total)`,\n );\n}\n\n/**\n * Resolves a scope by name. Accepts either the scoped name (used by Next.js\n * hosts that rewrite RSC data server-side) or the plain bundle name (used by\n * static/HTML hosts where chunks arrive unrewritten).\n */\nexport function getScope(name: string): RemoteScope | undefined {\n return getRegistry().get(name);\n}\n\n/** Formats a `[scopedName] path` string for use in chunk/module IDs. */\nexport function formatRemoteId(scope: RemoteScope, path: string): string {\n return `[${scope.scopedName}] ${path}`;\n}\n\n/**\n * Parses the `[bundle] path` format used in chunk/module IDs.\n * Uses REMOTE_COMPONENT_REGEX (the same pattern used by the module dispatcher\n * and script loader) so the two parsing paths can never diverge.\n */\nexport function parseRemoteId(id: string): {\n bundle: string;\n path: string;\n prefix: string;\n} {\n const groups = REMOTE_COMPONENT_REGEX.exec(id)?.groups;\n if (groups?.bundle && groups.id) {\n return {\n bundle: groups.bundle,\n path: groups.id,\n prefix: groups.prefix ?? '',\n };\n }\n return { bundle: 'default', path: id, prefix: '' };\n}\n"],"mappings":"AACA,SAAS,oBAAkC;AAC3C,SAAS,8BAA8B;AAEvC,SAAS,yBAAyB;AAClC,SAAS,UAAU,eAAe;AAiClC,SAAS,cAAwC;AAC/C,QAAM,OAAO;AACb,MAAI,CAAC,KAAK,6BAA6B;AACrC,SAAK,8BAA8B,oBAAI,IAAqB;AAAA,EAC9D;AACA,SAAO,KAAK;AAId;AAEO,SAAS,YACd,MACA,KACA,SACA,kBACa;AACb,QAAM,gBAAgB,IAAI,WAAW,SAAS;AAC9C,QAAM,aAAa,kBAAkB,MAAM;AAAA,IACzC,YAAY,IAAI;AAAA,IAChB;AAAA,EACF,CAAC;AACD,QAAM,YAAY,aAAa,UAAU;AACzC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,CAAC;AAAA,IACd,eAAe,CAAC;AAAA,IAChB,cAAc,CAAC;AAAA,EACjB;AACF;AAEO,SAAS,cAAc,OAA0B;AACtD,QAAM,WAAW,YAAY;AAC7B,WAAS,IAAI,MAAM,YAAY,KAAK;AAKpC,MAAI,MAAM,eAAe,MAAM,MAAM;AACnC,UAAM,WAAW,SAAS,IAAI,MAAM,IAAI;AACxC,QAAI,YAAY,SAAS,eAAe,MAAM,YAAY;AACxD;AAAA,QACE;AAAA,QACA,eAAe,MAAM,sCAAsC,SAAS,wCAC7C,MAAM;AAAA,MAC/B;AAAA,IACF;AACA,aAAS,IAAI,MAAM,MAAM,KAAK;AAAA,EAChC;AAEA;AAAA,IACE;AAAA,IACA,qBAAqB,MAAM,gBAAgB,SAAS;AAAA,EACtD;AACF;AAOO,SAAS,SAAS,MAAuC;AAC9D,SAAO,YAAY,EAAE,IAAI,IAAI;AAC/B;AAGO,SAAS,eAAe,OAAoB,MAAsB;AACvE,SAAO,IAAI,MAAM,eAAe;AAClC;AAOO,SAAS,cAAc,IAI5B;AACA,QAAM,SAAS,uBAAuB,KAAK,EAAE,GAAG;AAChD,MAAI,QAAQ,UAAU,OAAO,IAAI;AAC/B,WAAO;AAAA,MACL,QAAQ,OAAO;AAAA,MACf,MAAM,OAAO;AAAA,MACb,QAAQ,OAAO,UAAU;AAAA,IAC3B;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,WAAW,MAAM,IAAI,QAAQ,GAAG;AACnD;","names":[]}
1
+ {"version":3,"sources":["../../../../src/runtime/turbopack/remote-scope.ts"],"sourcesContent":["import type { InternalResolveClientUrl } from '#internal/host/server/types';\nimport { getBundleKey, type Runtime } from '#internal/runtime/constants';\nimport { getNamespace } from '#internal/runtime/namespace';\nimport { REMOTE_COMPONENT_REGEX } from '#internal/runtime/patterns';\nimport { computeScopedName } from '#internal/utils';\nimport { logDebug, logWarn } from '#internal/utils/logger';\n\n/**\n * Encapsulates all per-remote state so that two remotes sharing the same\n * bundle name but served from different origins never collide.\n *\n * A scope is created once per `setupRemoteScope` call and threaded\n * directly through internal code paths (chunk loading, module resolution,\n * shared modules). Global dispatchers (`__webpack_require__`,\n * `__webpack_chunk_load__`) only exist for external callers (RSC runtime)\n * and resolve the correct scope via the registry.\n */\nexport interface RemoteScope {\n /** Plain bundle name (e.g. \"remote-component-registry\") */\n name: string;\n /** Origin-qualified key — unique even when two remotes share a name */\n scopedName: string;\n /** Escaped key used as suffix for TURBOPACK_ globals */\n globalKey: string;\n /** Base URL for resolving relative chunk paths */\n url: URL;\n /** Bundler runtime type */\n runtime: Runtime;\n /** Proxy callback for routing chunks through the host */\n resolveClientUrl?: InternalResolveClientUrl;\n /** Per-scope cache of executed Turbopack module exports */\n moduleCache: Record<string, unknown>;\n /** Per-scope shared modules provided by the host (React, etc.) */\n sharedModules: Record<string, unknown>;\n /** Per-scope globalThis substitute passed to module initializers as `g` */\n moduleGlobal: Record<string, unknown>;\n /**\n * Webpack's bundle-scoped require function, populated from\n * `__remote_webpack_require__[bundleName]` for webpack remotes.\n * Undefined for turbopack remotes.\n */\n webpackRequire?: ((id: string | number) => unknown) & {\n m?: Record<string | number, (module: { exports: unknown }) => void>;\n type?: string;\n };\n /**\n * Flat array of captured turbopack module entries: [scriptEl, id, factory, ...].\n * Populated by the push interceptor in handleTurbopackChunk. This is the\n * primary source of truth for getTurbopackModules — immune to the turbopack\n * runtime replacing the TURBOPACK global (canary builds use a deferred-loading\n * pattern that swaps the array for an immediate-processing dispatcher).\n */\n turbopackModules: unknown[];\n}\n\nfunction getRegistry(): Map<string, RemoteScope> {\n return getNamespace().scopes;\n}\n\nexport function createScope(\n name: string,\n url: URL,\n runtime: Runtime,\n resolveClientUrl?: InternalResolveClientUrl,\n): RemoteScope {\n const isCrossOrigin = url.origin !== location.origin;\n const scopedName = computeScopedName(name, {\n remoteHost: url.host,\n isCrossOrigin,\n });\n const globalKey = getBundleKey(scopedName);\n return {\n name,\n scopedName,\n globalKey,\n url,\n runtime,\n resolveClientUrl,\n moduleCache: {},\n sharedModules: {},\n moduleGlobal: {},\n turbopackModules: [],\n };\n}\n\nexport function registerScope(scope: RemoteScope): void {\n const registry = getRegistry();\n registry.set(scope.scopedName, scope);\n\n // Also register under the plain name so hosts without server-side RSC\n // rewriting (static/HTML hosts) can look up cross-origin scopes by\n // the bundle name that appears in unrewritten chunk/module IDs.\n if (scope.scopedName !== scope.name) {\n const existing = registry.get(scope.name);\n if (existing && existing.scopedName !== scope.scopedName) {\n logWarn(\n 'RemoteScope',\n `Plain name \"${scope.name}\" already registered by scope \"${existing.scopedName}\" — ` +\n `overwriting with \"${scope.scopedName}\". Static hosts will only resolve the latest one.`,\n );\n }\n registry.set(scope.name, scope);\n }\n\n logDebug(\n 'RemoteScope',\n `Registered scope \"${scope.scopedName}\" (${registry.size} total)`,\n );\n}\n\n/**\n * Resolves a scope by name. Accepts either the scoped name (used by Next.js\n * hosts that rewrite RSC data server-side) or the plain bundle name (used by\n * static/HTML hosts where chunks arrive unrewritten).\n */\nexport function getScope(name: string): RemoteScope | undefined {\n return getRegistry().get(name);\n}\n\n/** Formats a `[scopedName] path` string for use in chunk/module IDs. */\nexport function formatRemoteId(scope: RemoteScope, path: string): string {\n return `[${scope.scopedName}] ${path}`;\n}\n\n/**\n * Parses the `[bundle] path` format used in chunk/module IDs.\n * Uses REMOTE_COMPONENT_REGEX (the same pattern used by the module dispatcher\n * and script loader) so the two parsing paths can never diverge.\n */\nexport function parseRemoteId(id: string): {\n bundle: string;\n path: string;\n prefix: string;\n} {\n const groups = REMOTE_COMPONENT_REGEX.exec(id)?.groups;\n if (groups?.bundle && groups.id) {\n return {\n bundle: groups.bundle,\n path: groups.id,\n prefix: groups.prefix ?? '',\n };\n }\n return { bundle: 'default', path: id, prefix: '' };\n}\n"],"mappings":"AACA,SAAS,oBAAkC;AAC3C,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AACvC,SAAS,yBAAyB;AAClC,SAAS,UAAU,eAAe;AAkDlC,SAAS,cAAwC;AAC/C,SAAO,aAAa,EAAE;AACxB;AAEO,SAAS,YACd,MACA,KACA,SACA,kBACa;AACb,QAAM,gBAAgB,IAAI,WAAW,SAAS;AAC9C,QAAM,aAAa,kBAAkB,MAAM;AAAA,IACzC,YAAY,IAAI;AAAA,IAChB;AAAA,EACF,CAAC;AACD,QAAM,YAAY,aAAa,UAAU;AACzC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,CAAC;AAAA,IACd,eAAe,CAAC;AAAA,IAChB,cAAc,CAAC;AAAA,IACf,kBAAkB,CAAC;AAAA,EACrB;AACF;AAEO,SAAS,cAAc,OAA0B;AACtD,QAAM,WAAW,YAAY;AAC7B,WAAS,IAAI,MAAM,YAAY,KAAK;AAKpC,MAAI,MAAM,eAAe,MAAM,MAAM;AACnC,UAAM,WAAW,SAAS,IAAI,MAAM,IAAI;AACxC,QAAI,YAAY,SAAS,eAAe,MAAM,YAAY;AACxD;AAAA,QACE;AAAA,QACA,eAAe,MAAM,sCAAsC,SAAS,wCAC7C,MAAM;AAAA,MAC/B;AAAA,IACF;AACA,aAAS,IAAI,MAAM,MAAM,KAAK;AAAA,EAChC;AAEA;AAAA,IACE;AAAA,IACA,qBAAqB,MAAM,gBAAgB,SAAS;AAAA,EACtD;AACF;AAOO,SAAS,SAAS,MAAuC;AAC9D,SAAO,YAAY,EAAE,IAAI,IAAI;AAC/B;AAGO,SAAS,eAAe,OAAoB,MAAsB;AACvE,SAAO,IAAI,MAAM,eAAe;AAClC;AAOO,SAAS,cAAc,IAI5B;AACA,QAAM,SAAS,uBAAuB,KAAK,EAAE,GAAG;AAChD,MAAI,QAAQ,UAAU,OAAO,IAAI;AAC/B,WAAO;AAAA,MACL,QAAQ,OAAO;AAAA,MACf,MAAM,OAAO;AAAA,MACb,QAAQ,OAAO,UAAU;AAAA,IAC3B;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,WAAW,MAAM,IAAI,QAAQ,GAAG;AACnD;","names":[]}
@@ -29,13 +29,13 @@ var import_patterns = require("./patterns");
29
29
  var import_remote_scope = require("./remote-scope");
30
30
  const DEDUPLICATION_WARNING = "This module will not be deduplicated \u2014 the remote may load its own copy, which can cause duplicate instance errors (e.g. invalid hook calls if React is loaded twice).";
31
31
  function getTurbopackModules(scope) {
32
+ if (scope.turbopackModules.length > 0) {
33
+ return scope.turbopackModules;
34
+ }
32
35
  const self = globalThis;
33
36
  const raw = self[`TURBOPACK_${scope.globalKey}`];
34
37
  if (!raw)
35
38
  return void 0;
36
- if (typeof raw === "object" && "__chunks__" in raw) {
37
- return raw.__chunks__.flat();
38
- }
39
39
  if (Array.isArray(raw)) {
40
40
  return raw.flat();
41
41
  }
@@ -59,7 +59,11 @@ async function initializeSharedModules(scope, hostShared = {}, remoteShared = {}
59
59
  if (sharedModuleInitializerIndex > 0) {
60
60
  const sharedModuleInitializerCode = allModules[sharedModuleInitializerIndex].toString();
61
61
  const sharedModuleInitializerId = allModules[sharedModuleInitializerIndex - 1];
62
- const { sharedModuleId } = import_patterns.REMOTE_SHARED_ASSIGNMENT_RE.exec(sharedModuleInitializerCode)?.groups ?? {};
62
+ const sharedModuleId = (0, import_patterns.extractGroup)(
63
+ import_patterns.REMOTE_SHARED_ASSIGNMENT_RE,
64
+ sharedModuleInitializerCode,
65
+ "sharedModuleId"
66
+ );
63
67
  if (sharedModuleId) {
64
68
  const { default: sharedModuleInitializerInstance } = (0, import_module.handleTurbopackModule)(
65
69
  scope,
@@ -117,20 +121,22 @@ async function initializeSharedModules(scope, hostShared = {}, remoteShared = {}
117
121
  }
118
122
  function extractSharedModuleIds(shared, scope) {
119
123
  return Object.entries(shared).filter(([, value]) => typeof value === "function").reduce((acc, [key, value]) => {
120
- const { asyncSharedModuleId } = import_patterns.ASYNC_MODULE_LOADER_RE.exec(value.toString())?.groups ?? {};
124
+ const asyncSharedModuleId = (0, import_patterns.extractGroup)(
125
+ import_patterns.ASYNC_MODULE_LOADER_RE,
126
+ value.toString(),
127
+ "asyncSharedModuleId"
128
+ );
121
129
  if (asyncSharedModuleId) {
122
- const asyncSharedModuleIdNumber = Number(asyncSharedModuleId);
123
- let asyncSharedModule;
124
- const turbopackModules = getTurbopackModules(scope) ?? [];
125
- const asyncSharedModuleIdIndex = turbopackModules.indexOf(
126
- asyncSharedModuleIdNumber
130
+ const asyncSharedModule = (0, import_module.findModuleInit)(
131
+ getTurbopackModules(scope),
132
+ asyncSharedModuleId
127
133
  );
128
- if (asyncSharedModuleIdIndex !== -1 && typeof turbopackModules[asyncSharedModuleIdIndex + 1] === "function") {
129
- asyncSharedModule = turbopackModules[asyncSharedModuleIdIndex + 1];
130
- }
131
134
  if (asyncSharedModule) {
132
- const asyncSharedModuleCode = asyncSharedModule.toString();
133
- const { sharedModuleId } = import_patterns.ASYNC_MODULE_RESOLVE_RE.exec(asyncSharedModuleCode)?.groups ?? import_patterns.ASYNC_MODULE_ALL_RE.exec(asyncSharedModuleCode)?.groups ?? {};
135
+ const sharedModuleId = (0, import_patterns.extractGroup)(
136
+ import_patterns.ASYNC_MODULE_CALLBACK_RE,
137
+ asyncSharedModule.toString(),
138
+ "sharedModuleId"
139
+ );
134
140
  acc[sharedModuleId ?? asyncSharedModuleId] = key.replace(
135
141
  "__remote_shared_module_",
136
142
  ""
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/runtime/turbopack/shared-modules.ts"],"sourcesContent":["import type { GlobalScope } from '#internal/runtime/types';\nimport { logDebug, logError, logWarn } from '#internal/utils/logger';\nimport { handleTurbopackModule } from './module';\nimport {\n ASYNC_MODULE_ALL_RE,\n ASYNC_MODULE_LOADER_RE,\n ASYNC_MODULE_RESOLVE_RE,\n REMOTE_SHARED_ASSIGNMENT_RE,\n REMOTE_SHARED_MARKER_RE,\n} from './patterns';\nimport { formatRemoteId, type RemoteScope } from './remote-scope';\n\nconst DEDUPLICATION_WARNING =\n 'This module will not be deduplicated — the remote may load its own copy, ' +\n 'which can cause duplicate instance errors (e.g. invalid hook calls if React is loaded twice).';\n\n/**\n * Reads the TURBOPACK global for a scope, normalizing the push-based\n * `__chunks__` format into a flat module list when needed.\n */\nexport function getTurbopackModules(scope: RemoteScope): unknown[] | undefined {\n const self = globalThis as GlobalScope;\n const raw = self[`TURBOPACK_${scope.globalKey}`];\n if (!raw) return undefined;\n\n if (typeof raw === 'object' && '__chunks__' in (raw as object)) {\n return (raw as { __chunks__: unknown[][] }).__chunks__.flat();\n }\n if (Array.isArray(raw)) {\n return (raw as unknown[]).flat();\n }\n return Object.entries(raw as Record<string, unknown>).flat();\n}\n\n/**\n * Initializes shared modules between the host application and remote components.\n * This enables sharing of common dependencies like React to avoid duplicate instances.\n *\n * The function works by:\n * 1. Looking for a shared module initializer in the Turbopack bundle\n * 2. Extracting module IDs from the initializer\n * 3. Loading the corresponding host modules and mapping them to the remote's expected IDs\n */\nexport async function initializeSharedModules(\n scope: RemoteScope,\n hostShared: Record<string, (bundle?: string) => Promise<unknown>> = {},\n remoteShared: Record<string, string> = {},\n // biome-ignore lint/suspicious/noConfusingVoidType: Runtime is undefined but in TS land service it is void\n): Promise<void[]> {\n const allModules = getTurbopackModules(scope);\n\n logDebug(\n 'SharedModules',\n `initializeSharedModules: scope=\"${scope.scopedName}\", ` +\n `allModules=${allModules ? allModules.length : 'null'}, ` +\n `hostShared=[${Object.keys(hostShared).join(', ')}], ` +\n `remoteShared=${JSON.stringify(remoteShared)}`,\n );\n\n let sharedModuleInitializer: Promise<{\n shared: Record<string, string | (() => Promise<unknown>)>;\n }> | null = null;\n\n // find the shared module initializer in the Turbopack bundle\n if (allModules) {\n // find the shared module initializer module id by looking for\n // a function that contains the TURBOPACK_REMOTE_SHARED pattern\n const sharedModuleInitializerIndex = allModules.findIndex((idOrFunc) => {\n if (typeof idOrFunc !== 'function') {\n return false;\n }\n const funcCode = idOrFunc.toString();\n return REMOTE_SHARED_MARKER_RE.test(funcCode);\n });\n\n // if found, extract the shared module initializer\n // first element in the array is always the source script element\n if (sharedModuleInitializerIndex > 0) {\n const sharedModuleInitializerCode = (\n allModules[sharedModuleInitializerIndex] as () => unknown\n ).toString();\n const sharedModuleInitializerId = allModules[\n sharedModuleInitializerIndex - 1\n ] as string | number;\n // extract the shared module id from the function code\n const { sharedModuleId } =\n REMOTE_SHARED_ASSIGNMENT_RE.exec(sharedModuleInitializerCode)?.groups ??\n {};\n // load the shared module initializer using the extracted module id\n if (sharedModuleId) {\n const { default: sharedModuleInitializerInstance } =\n handleTurbopackModule(\n scope,\n sharedModuleId,\n formatRemoteId(scope, String(sharedModuleInitializerId)),\n ) as {\n default: Promise<{\n shared: Record<string, string | (() => Promise<unknown>)>;\n }>;\n };\n sharedModuleInitializer = sharedModuleInitializerInstance;\n }\n }\n\n // if we have a shared module initializer, load the shared modules from the host application\n if (sharedModuleInitializer) {\n const { shared } = await sharedModuleInitializer;\n // map shared module ids to their initializer functions\n const sharedModuleIds = extractSharedModuleIds(shared, scope);\n logDebug(\n 'SharedModules',\n `Resolved shared modules for scope=\"${scope.scopedName}\": ${JSON.stringify(sharedModuleIds)}`,\n );\n\n // load shared modules from the host application\n return Promise.all(\n Object.entries(sharedModuleIds).map(async ([id, module]) => {\n if (hostShared[module]) {\n scope.sharedModules[id] = await hostShared[module](scope.name);\n } else {\n logError(\n 'SharedModules',\n `Host shared module \"${module}\" not found for ID ${id}. ${DEDUPLICATION_WARNING}`,\n );\n }\n }),\n );\n }\n\n logWarn(\n 'SharedModules',\n `No shared module initializer found in bundle for scope=\"${scope.scopedName}\" — falling back to remoteShared mapping`,\n );\n } else {\n logWarn(\n 'SharedModules',\n `No TURBOPACK modules found for scope=\"${scope.scopedName}\" (TURBOPACK_${scope.globalKey} is empty)`,\n );\n }\n\n // fallback: ensure that the shared modules are initialized using remoteShared mapping\n return Promise.all(\n Object.entries(remoteShared).map(async ([id, module]) => {\n if (hostShared[module]) {\n const normalizedId = id.replace('[app-ssr]', '[app-client]');\n scope.sharedModules[normalizedId] = await hostShared[module](\n scope.name,\n );\n } else {\n logError(\n 'SharedModules',\n `Shared module \"${module}\" not found for \"${scope.name}\". ${DEDUPLICATION_WARNING}`,\n );\n }\n }),\n );\n}\n\n/**\n * Extracts shared module IDs from the shared module initializer functions.\n * This parses the minified Turbopack code to find the module ID mappings.\n */\nfunction extractSharedModuleIds(\n shared: Record<string, string | (() => Promise<unknown>)>,\n scope: RemoteScope,\n): Record<string, string> {\n return Object.entries(shared)\n .filter(([, value]) => typeof value === 'function')\n .reduce<Record<string, string>>((acc, [key, value]) => {\n const { asyncSharedModuleId } =\n ASYNC_MODULE_LOADER_RE.exec(value.toString())?.groups ?? {};\n\n if (asyncSharedModuleId) {\n const asyncSharedModuleIdNumber = Number(asyncSharedModuleId);\n\n let asyncSharedModule: (() => unknown) | undefined;\n const turbopackModules = getTurbopackModules(scope) ?? [];\n const asyncSharedModuleIdIndex = turbopackModules.indexOf(\n asyncSharedModuleIdNumber,\n );\n if (\n asyncSharedModuleIdIndex !== -1 &&\n typeof turbopackModules[asyncSharedModuleIdIndex + 1] === 'function'\n ) {\n asyncSharedModule = turbopackModules[\n asyncSharedModuleIdIndex + 1\n ] as () => unknown;\n }\n if (asyncSharedModule) {\n const asyncSharedModuleCode = asyncSharedModule.toString();\n // Try both Promise.resolve and Promise.all patterns\n const { sharedModuleId } =\n ASYNC_MODULE_RESOLVE_RE.exec(asyncSharedModuleCode)?.groups ??\n ASYNC_MODULE_ALL_RE.exec(asyncSharedModuleCode)?.groups ??\n {};\n // map the shared module id to the actual module name\n acc[sharedModuleId ?? asyncSharedModuleId] = key.replace(\n '__remote_shared_module_',\n '',\n );\n }\n }\n return acc;\n }, {});\n}\n\n/**\n * Returns a shared module for the given scope and module ID.\n * Shared modules are common dependencies like React that are provided by the host.\n */\nexport function getSharedModule(\n scope: RemoteScope,\n id: string | number,\n): unknown {\n const idStr = String(id);\n\n // Exact match first (covers both string and numeric IDs)\n if (scope.sharedModules[idStr] !== undefined) {\n return scope.sharedModules[idStr];\n }\n\n // Fallback: the id may be a bundle-prefixed string like \"[bundle] /react/index.js\"\n // that contains the shared module key as a suffix. Only match when the key\n // appears as a complete suffix segment to avoid \"react\" matching \"react-dom\".\n for (const [key, value] of Object.entries(scope.sharedModules)) {\n if (typeof value !== 'undefined' && idStr !== key && idStr.endsWith(key)) {\n return value;\n }\n }\n\n return null;\n}\n"],"mappings":"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","names":["module"]}
1
+ {"version":3,"sources":["../../../../src/runtime/turbopack/shared-modules.ts"],"sourcesContent":["import type { GlobalScope } from '#internal/runtime/types';\nimport { logDebug, logError, logWarn } from '#internal/utils/logger';\nimport { findModuleInit, handleTurbopackModule } from './module';\nimport {\n ASYNC_MODULE_CALLBACK_RE,\n ASYNC_MODULE_LOADER_RE,\n extractGroup,\n REMOTE_SHARED_ASSIGNMENT_RE,\n REMOTE_SHARED_MARKER_RE,\n} from './patterns';\nimport { formatRemoteId, type RemoteScope } from './remote-scope';\n\nconst DEDUPLICATION_WARNING =\n 'This module will not be deduplicated — the remote may load its own copy, ' +\n 'which can cause duplicate instance errors (e.g. invalid hook calls if React is loaded twice).';\n\n/**\n * Returns the flat module list for a scope.\n *\n * The primary source is `scope.turbopackModules` — a flat array populated by\n * the push interceptor in handleTurbopackChunk. This is immune to the\n * turbopack runtime replacing the TURBOPACK global (canary builds swap the\n * array for a deferred-loading dispatcher object).\n *\n * Falls back to reading the global for pre-populated bundles where the push\n * interceptor was never installed.\n */\nexport function getTurbopackModules(scope: RemoteScope): unknown[] | undefined {\n if (scope.turbopackModules.length > 0) {\n return scope.turbopackModules;\n }\n\n // Fallback: read the global for pre-populated bundles or legacy setups.\n const self = globalThis as GlobalScope;\n const raw = self[`TURBOPACK_${scope.globalKey}`];\n if (!raw) return undefined;\n\n if (Array.isArray(raw)) {\n return (raw as unknown[]).flat();\n }\n return Object.entries(raw as Record<string, unknown>).flat();\n}\n\n/**\n * Initializes shared modules between the host application and remote components.\n * This enables sharing of common dependencies like React to avoid duplicate instances.\n *\n * The function works by:\n * 1. Looking for a shared module initializer in the Turbopack bundle\n * 2. Extracting module IDs from the initializer\n * 3. Loading the corresponding host modules and mapping them to the remote's expected IDs\n */\nexport async function initializeSharedModules(\n scope: RemoteScope,\n hostShared: Record<string, (bundle?: string) => Promise<unknown>> = {},\n remoteShared: Record<string, string> = {},\n // biome-ignore lint/suspicious/noConfusingVoidType: Runtime is undefined but in TS land service it is void\n): Promise<void[]> {\n const allModules = getTurbopackModules(scope);\n\n logDebug(\n 'SharedModules',\n `initializeSharedModules: scope=\"${scope.scopedName}\", ` +\n `allModules=${allModules ? allModules.length : 'null'}, ` +\n `hostShared=[${Object.keys(hostShared).join(', ')}], ` +\n `remoteShared=${JSON.stringify(remoteShared)}`,\n );\n\n let sharedModuleInitializer: Promise<{\n shared: Record<string, string | (() => Promise<unknown>)>;\n }> | null = null;\n\n // find the shared module initializer in the Turbopack bundle\n if (allModules) {\n // find the shared module initializer module id by looking for\n // a function that contains the TURBOPACK_REMOTE_SHARED pattern\n const sharedModuleInitializerIndex = allModules.findIndex((idOrFunc) => {\n if (typeof idOrFunc !== 'function') {\n return false;\n }\n const funcCode = idOrFunc.toString();\n return REMOTE_SHARED_MARKER_RE.test(funcCode);\n });\n\n // if found, extract the shared module initializer\n // first element in the array is always the source script element\n if (sharedModuleInitializerIndex > 0) {\n const sharedModuleInitializerCode = (\n allModules[sharedModuleInitializerIndex] as () => unknown\n ).toString();\n const sharedModuleInitializerId = allModules[\n sharedModuleInitializerIndex - 1\n ] as string | number;\n // extract the shared module id from the function code\n const sharedModuleId = extractGroup(\n REMOTE_SHARED_ASSIGNMENT_RE,\n sharedModuleInitializerCode,\n 'sharedModuleId',\n );\n // load the shared module initializer using the extracted module id\n if (sharedModuleId) {\n const { default: sharedModuleInitializerInstance } =\n handleTurbopackModule(\n scope,\n sharedModuleId,\n formatRemoteId(scope, String(sharedModuleInitializerId)),\n ) as {\n default: Promise<{\n shared: Record<string, string | (() => Promise<unknown>)>;\n }>;\n };\n sharedModuleInitializer = sharedModuleInitializerInstance;\n }\n }\n\n // if we have a shared module initializer, load the shared modules from the host application\n if (sharedModuleInitializer) {\n const { shared } = await sharedModuleInitializer;\n // map shared module ids to their initializer functions\n const sharedModuleIds = extractSharedModuleIds(shared, scope);\n logDebug(\n 'SharedModules',\n `Resolved shared modules for scope=\"${scope.scopedName}\": ${JSON.stringify(sharedModuleIds)}`,\n );\n\n // load shared modules from the host application\n return Promise.all(\n Object.entries(sharedModuleIds).map(async ([id, module]) => {\n if (hostShared[module]) {\n scope.sharedModules[id] = await hostShared[module](scope.name);\n } else {\n logError(\n 'SharedModules',\n `Host shared module \"${module}\" not found for ID ${id}. ${DEDUPLICATION_WARNING}`,\n );\n }\n }),\n );\n }\n\n logWarn(\n 'SharedModules',\n `No shared module initializer found in bundle for scope=\"${scope.scopedName}\" — falling back to remoteShared mapping`,\n );\n } else {\n logWarn(\n 'SharedModules',\n `No TURBOPACK modules found for scope=\"${scope.scopedName}\" (TURBOPACK_${scope.globalKey} is empty)`,\n );\n }\n\n // fallback: ensure that the shared modules are initialized using remoteShared mapping\n return Promise.all(\n Object.entries(remoteShared).map(async ([id, module]) => {\n if (hostShared[module]) {\n const normalizedId = id.replace('[app-ssr]', '[app-client]');\n scope.sharedModules[normalizedId] = await hostShared[module](\n scope.name,\n );\n } else {\n logError(\n 'SharedModules',\n `Shared module \"${module}\" not found for \"${scope.name}\". ${DEDUPLICATION_WARNING}`,\n );\n }\n }),\n );\n}\n\n/**\n * Extracts shared module IDs from the shared module initializer functions.\n * This parses the minified Turbopack code to find the module ID mappings.\n */\nfunction extractSharedModuleIds(\n shared: Record<string, string | (() => Promise<unknown>)>,\n scope: RemoteScope,\n): Record<string, string> {\n return Object.entries(shared)\n .filter(([, value]) => typeof value === 'function')\n .reduce<Record<string, string>>((acc, [key, value]) => {\n const asyncSharedModuleId = extractGroup(\n ASYNC_MODULE_LOADER_RE,\n value.toString(),\n 'asyncSharedModuleId',\n );\n\n if (asyncSharedModuleId) {\n const asyncSharedModule = findModuleInit(\n getTurbopackModules(scope),\n asyncSharedModuleId,\n );\n if (asyncSharedModule) {\n const sharedModuleId = extractGroup(\n ASYNC_MODULE_CALLBACK_RE,\n asyncSharedModule.toString(),\n 'sharedModuleId',\n );\n // map the shared module id to the actual module name\n acc[sharedModuleId ?? asyncSharedModuleId] = key.replace(\n '__remote_shared_module_',\n '',\n );\n }\n }\n return acc;\n }, {});\n}\n\n/**\n * Returns a shared module for the given scope and module ID.\n * Shared modules are common dependencies like React that are provided by the host.\n */\nexport function getSharedModule(\n scope: RemoteScope,\n id: string | number,\n): unknown {\n const idStr = String(id);\n\n // Exact match first (covers both string and numeric IDs)\n if (scope.sharedModules[idStr] !== undefined) {\n return scope.sharedModules[idStr];\n }\n\n // Fallback: the id may be a bundle-prefixed string like \"[bundle] /react/index.js\"\n // that contains the shared module key as a suffix. Only match when the key\n // appears as a complete suffix segment to avoid \"react\" matching \"react-dom\".\n for (const [key, value] of Object.entries(scope.sharedModules)) {\n if (typeof value !== 'undefined' && idStr !== key && idStr.endsWith(key)) {\n return value;\n }\n }\n\n return null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,oBAA4C;AAC5C,oBAAsD;AACtD,sBAMO;AACP,0BAAiD;AAEjD,MAAM,wBACJ;AAcK,SAAS,oBAAoB,OAA2C;AAC7E,MAAI,MAAM,iBAAiB,SAAS,GAAG;AACrC,WAAO,MAAM;AAAA,EACf;AAGA,QAAM,OAAO;AACb,QAAM,MAAM,KAAK,aAAa,MAAM,WAAW;AAC/C,MAAI,CAAC;AAAK,WAAO;AAEjB,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,WAAQ,IAAkB,KAAK;AAAA,EACjC;AACA,SAAO,OAAO,QAAQ,GAA8B,EAAE,KAAK;AAC7D;AAWA,eAAsB,wBACpB,OACA,aAAoE,CAAC,GACrE,eAAuC,CAAC,GAEvB;AACjB,QAAM,aAAa,oBAAoB,KAAK;AAE5C;AAAA,IACE;AAAA,IACA,mCAAmC,MAAM,2BACzB,aAAa,WAAW,SAAS,uBAChC,OAAO,KAAK,UAAU,EAAE,KAAK,IAAI,oBAChC,KAAK,UAAU,YAAY;AAAA,EAC/C;AAEA,MAAI,0BAEQ;AAGZ,MAAI,YAAY;AAGd,UAAM,+BAA+B,WAAW,UAAU,CAAC,aAAa;AACtE,UAAI,OAAO,aAAa,YAAY;AAClC,eAAO;AAAA,MACT;AACA,YAAM,WAAW,SAAS,SAAS;AACnC,aAAO,wCAAwB,KAAK,QAAQ;AAAA,IAC9C,CAAC;AAID,QAAI,+BAA+B,GAAG;AACpC,YAAM,8BACJ,WAAW,4BAA4B,EACvC,SAAS;AACX,YAAM,4BAA4B,WAChC,+BAA+B,CACjC;AAEA,YAAM,qBAAiB;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,UAAI,gBAAgB;AAClB,cAAM,EAAE,SAAS,gCAAgC,QAC/C;AAAA,UACE;AAAA,UACA;AAAA,cACA,oCAAe,OAAO,OAAO,yBAAyB,CAAC;AAAA,QACzD;AAKF,kCAA0B;AAAA,MAC5B;AAAA,IACF;AAGA,QAAI,yBAAyB;AAC3B,YAAM,EAAE,OAAO,IAAI,MAAM;AAEzB,YAAM,kBAAkB,uBAAuB,QAAQ,KAAK;AAC5D;AAAA,QACE;AAAA,QACA,sCAAsC,MAAM,gBAAgB,KAAK,UAAU,eAAe;AAAA,MAC5F;AAGA,aAAO,QAAQ;AAAA,QACb,OAAO,QAAQ,eAAe,EAAE,IAAI,OAAO,CAAC,IAAIA,OAAM,MAAM;AAC1D,cAAI,WAAWA,OAAM,GAAG;AACtB,kBAAM,cAAc,EAAE,IAAI,MAAM,WAAWA,OAAM,EAAE,MAAM,IAAI;AAAA,UAC/D,OAAO;AACL;AAAA,cACE;AAAA,cACA,uBAAuBA,6BAA4B,OAAO;AAAA,YAC5D;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA;AAAA,MACE;AAAA,MACA,2DAA2D,MAAM;AAAA,IACnE;AAAA,EACF,OAAO;AACL;AAAA,MACE;AAAA,MACA,yCAAyC,MAAM,0BAA0B,MAAM;AAAA,IACjF;AAAA,EACF;AAGA,SAAO,QAAQ;AAAA,IACb,OAAO,QAAQ,YAAY,EAAE,IAAI,OAAO,CAAC,IAAIA,OAAM,MAAM;AACvD,UAAI,WAAWA,OAAM,GAAG;AACtB,cAAM,eAAe,GAAG,QAAQ,aAAa,cAAc;AAC3D,cAAM,cAAc,YAAY,IAAI,MAAM,WAAWA,OAAM;AAAA,UACzD,MAAM;AAAA,QACR;AAAA,MACF,OAAO;AACL;AAAA,UACE;AAAA,UACA,kBAAkBA,2BAA0B,MAAM,UAAU;AAAA,QAC9D;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAMA,SAAS,uBACP,QACA,OACwB;AACxB,SAAO,OAAO,QAAQ,MAAM,EACzB,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,OAAO,UAAU,UAAU,EACjD,OAA+B,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM;AACrD,UAAM,0BAAsB;AAAA,MAC1B;AAAA,MACA,MAAM,SAAS;AAAA,MACf;AAAA,IACF;AAEA,QAAI,qBAAqB;AACvB,YAAM,wBAAoB;AAAA,QACxB,oBAAoB,KAAK;AAAA,QACzB;AAAA,MACF;AACA,UAAI,mBAAmB;AACrB,cAAM,qBAAiB;AAAA,UACrB;AAAA,UACA,kBAAkB,SAAS;AAAA,UAC3B;AAAA,QACF;AAEA,YAAI,kBAAkB,mBAAmB,IAAI,IAAI;AAAA,UAC/C;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AACT;AAMO,SAAS,gBACd,OACA,IACS;AACT,QAAM,QAAQ,OAAO,EAAE;AAGvB,MAAI,MAAM,cAAc,KAAK,MAAM,QAAW;AAC5C,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC;AAKA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,aAAa,GAAG;AAC9D,QAAI,OAAO,UAAU,eAAe,UAAU,OAAO,MAAM,SAAS,GAAG,GAAG;AACxE,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;","names":["module"]}
@@ -3,8 +3,15 @@ import '../url/resolve-client-url.js';
3
3
  import '../constants.js';
4
4
 
5
5
  /**
6
- * Reads the TURBOPACK global for a scope, normalizing the push-based
7
- * `__chunks__` format into a flat module list when needed.
6
+ * Returns the flat module list for a scope.
7
+ *
8
+ * The primary source is `scope.turbopackModules` — a flat array populated by
9
+ * the push interceptor in handleTurbopackChunk. This is immune to the
10
+ * turbopack runtime replacing the TURBOPACK global (canary builds swap the
11
+ * array for a deferred-loading dispatcher object).
12
+ *
13
+ * Falls back to reading the global for pre-populated bundles where the push
14
+ * interceptor was never installed.
8
15
  */
9
16
  declare function getTurbopackModules(scope: RemoteScope): unknown[] | undefined;
10
17
  /**
@@ -1,22 +1,22 @@
1
1
  import { logDebug, logError, logWarn } from "#internal/utils/logger";
2
- import { handleTurbopackModule } from "./module";
2
+ import { findModuleInit, handleTurbopackModule } from "./module";
3
3
  import {
4
- ASYNC_MODULE_ALL_RE,
4
+ ASYNC_MODULE_CALLBACK_RE,
5
5
  ASYNC_MODULE_LOADER_RE,
6
- ASYNC_MODULE_RESOLVE_RE,
6
+ extractGroup,
7
7
  REMOTE_SHARED_ASSIGNMENT_RE,
8
8
  REMOTE_SHARED_MARKER_RE
9
9
  } from "./patterns";
10
10
  import { formatRemoteId } from "./remote-scope";
11
11
  const DEDUPLICATION_WARNING = "This module will not be deduplicated \u2014 the remote may load its own copy, which can cause duplicate instance errors (e.g. invalid hook calls if React is loaded twice).";
12
12
  function getTurbopackModules(scope) {
13
+ if (scope.turbopackModules.length > 0) {
14
+ return scope.turbopackModules;
15
+ }
13
16
  const self = globalThis;
14
17
  const raw = self[`TURBOPACK_${scope.globalKey}`];
15
18
  if (!raw)
16
19
  return void 0;
17
- if (typeof raw === "object" && "__chunks__" in raw) {
18
- return raw.__chunks__.flat();
19
- }
20
20
  if (Array.isArray(raw)) {
21
21
  return raw.flat();
22
22
  }
@@ -40,7 +40,11 @@ async function initializeSharedModules(scope, hostShared = {}, remoteShared = {}
40
40
  if (sharedModuleInitializerIndex > 0) {
41
41
  const sharedModuleInitializerCode = allModules[sharedModuleInitializerIndex].toString();
42
42
  const sharedModuleInitializerId = allModules[sharedModuleInitializerIndex - 1];
43
- const { sharedModuleId } = REMOTE_SHARED_ASSIGNMENT_RE.exec(sharedModuleInitializerCode)?.groups ?? {};
43
+ const sharedModuleId = extractGroup(
44
+ REMOTE_SHARED_ASSIGNMENT_RE,
45
+ sharedModuleInitializerCode,
46
+ "sharedModuleId"
47
+ );
44
48
  if (sharedModuleId) {
45
49
  const { default: sharedModuleInitializerInstance } = handleTurbopackModule(
46
50
  scope,
@@ -98,20 +102,22 @@ async function initializeSharedModules(scope, hostShared = {}, remoteShared = {}
98
102
  }
99
103
  function extractSharedModuleIds(shared, scope) {
100
104
  return Object.entries(shared).filter(([, value]) => typeof value === "function").reduce((acc, [key, value]) => {
101
- const { asyncSharedModuleId } = ASYNC_MODULE_LOADER_RE.exec(value.toString())?.groups ?? {};
105
+ const asyncSharedModuleId = extractGroup(
106
+ ASYNC_MODULE_LOADER_RE,
107
+ value.toString(),
108
+ "asyncSharedModuleId"
109
+ );
102
110
  if (asyncSharedModuleId) {
103
- const asyncSharedModuleIdNumber = Number(asyncSharedModuleId);
104
- let asyncSharedModule;
105
- const turbopackModules = getTurbopackModules(scope) ?? [];
106
- const asyncSharedModuleIdIndex = turbopackModules.indexOf(
107
- asyncSharedModuleIdNumber
111
+ const asyncSharedModule = findModuleInit(
112
+ getTurbopackModules(scope),
113
+ asyncSharedModuleId
108
114
  );
109
- if (asyncSharedModuleIdIndex !== -1 && typeof turbopackModules[asyncSharedModuleIdIndex + 1] === "function") {
110
- asyncSharedModule = turbopackModules[asyncSharedModuleIdIndex + 1];
111
- }
112
115
  if (asyncSharedModule) {
113
- const asyncSharedModuleCode = asyncSharedModule.toString();
114
- const { sharedModuleId } = ASYNC_MODULE_RESOLVE_RE.exec(asyncSharedModuleCode)?.groups ?? ASYNC_MODULE_ALL_RE.exec(asyncSharedModuleCode)?.groups ?? {};
116
+ const sharedModuleId = extractGroup(
117
+ ASYNC_MODULE_CALLBACK_RE,
118
+ asyncSharedModule.toString(),
119
+ "sharedModuleId"
120
+ );
115
121
  acc[sharedModuleId ?? asyncSharedModuleId] = key.replace(
116
122
  "__remote_shared_module_",
117
123
  ""
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/runtime/turbopack/shared-modules.ts"],"sourcesContent":["import type { GlobalScope } from '#internal/runtime/types';\nimport { logDebug, logError, logWarn } from '#internal/utils/logger';\nimport { handleTurbopackModule } from './module';\nimport {\n ASYNC_MODULE_ALL_RE,\n ASYNC_MODULE_LOADER_RE,\n ASYNC_MODULE_RESOLVE_RE,\n REMOTE_SHARED_ASSIGNMENT_RE,\n REMOTE_SHARED_MARKER_RE,\n} from './patterns';\nimport { formatRemoteId, type RemoteScope } from './remote-scope';\n\nconst DEDUPLICATION_WARNING =\n 'This module will not be deduplicated — the remote may load its own copy, ' +\n 'which can cause duplicate instance errors (e.g. invalid hook calls if React is loaded twice).';\n\n/**\n * Reads the TURBOPACK global for a scope, normalizing the push-based\n * `__chunks__` format into a flat module list when needed.\n */\nexport function getTurbopackModules(scope: RemoteScope): unknown[] | undefined {\n const self = globalThis as GlobalScope;\n const raw = self[`TURBOPACK_${scope.globalKey}`];\n if (!raw) return undefined;\n\n if (typeof raw === 'object' && '__chunks__' in (raw as object)) {\n return (raw as { __chunks__: unknown[][] }).__chunks__.flat();\n }\n if (Array.isArray(raw)) {\n return (raw as unknown[]).flat();\n }\n return Object.entries(raw as Record<string, unknown>).flat();\n}\n\n/**\n * Initializes shared modules between the host application and remote components.\n * This enables sharing of common dependencies like React to avoid duplicate instances.\n *\n * The function works by:\n * 1. Looking for a shared module initializer in the Turbopack bundle\n * 2. Extracting module IDs from the initializer\n * 3. Loading the corresponding host modules and mapping them to the remote's expected IDs\n */\nexport async function initializeSharedModules(\n scope: RemoteScope,\n hostShared: Record<string, (bundle?: string) => Promise<unknown>> = {},\n remoteShared: Record<string, string> = {},\n // biome-ignore lint/suspicious/noConfusingVoidType: Runtime is undefined but in TS land service it is void\n): Promise<void[]> {\n const allModules = getTurbopackModules(scope);\n\n logDebug(\n 'SharedModules',\n `initializeSharedModules: scope=\"${scope.scopedName}\", ` +\n `allModules=${allModules ? allModules.length : 'null'}, ` +\n `hostShared=[${Object.keys(hostShared).join(', ')}], ` +\n `remoteShared=${JSON.stringify(remoteShared)}`,\n );\n\n let sharedModuleInitializer: Promise<{\n shared: Record<string, string | (() => Promise<unknown>)>;\n }> | null = null;\n\n // find the shared module initializer in the Turbopack bundle\n if (allModules) {\n // find the shared module initializer module id by looking for\n // a function that contains the TURBOPACK_REMOTE_SHARED pattern\n const sharedModuleInitializerIndex = allModules.findIndex((idOrFunc) => {\n if (typeof idOrFunc !== 'function') {\n return false;\n }\n const funcCode = idOrFunc.toString();\n return REMOTE_SHARED_MARKER_RE.test(funcCode);\n });\n\n // if found, extract the shared module initializer\n // first element in the array is always the source script element\n if (sharedModuleInitializerIndex > 0) {\n const sharedModuleInitializerCode = (\n allModules[sharedModuleInitializerIndex] as () => unknown\n ).toString();\n const sharedModuleInitializerId = allModules[\n sharedModuleInitializerIndex - 1\n ] as string | number;\n // extract the shared module id from the function code\n const { sharedModuleId } =\n REMOTE_SHARED_ASSIGNMENT_RE.exec(sharedModuleInitializerCode)?.groups ??\n {};\n // load the shared module initializer using the extracted module id\n if (sharedModuleId) {\n const { default: sharedModuleInitializerInstance } =\n handleTurbopackModule(\n scope,\n sharedModuleId,\n formatRemoteId(scope, String(sharedModuleInitializerId)),\n ) as {\n default: Promise<{\n shared: Record<string, string | (() => Promise<unknown>)>;\n }>;\n };\n sharedModuleInitializer = sharedModuleInitializerInstance;\n }\n }\n\n // if we have a shared module initializer, load the shared modules from the host application\n if (sharedModuleInitializer) {\n const { shared } = await sharedModuleInitializer;\n // map shared module ids to their initializer functions\n const sharedModuleIds = extractSharedModuleIds(shared, scope);\n logDebug(\n 'SharedModules',\n `Resolved shared modules for scope=\"${scope.scopedName}\": ${JSON.stringify(sharedModuleIds)}`,\n );\n\n // load shared modules from the host application\n return Promise.all(\n Object.entries(sharedModuleIds).map(async ([id, module]) => {\n if (hostShared[module]) {\n scope.sharedModules[id] = await hostShared[module](scope.name);\n } else {\n logError(\n 'SharedModules',\n `Host shared module \"${module}\" not found for ID ${id}. ${DEDUPLICATION_WARNING}`,\n );\n }\n }),\n );\n }\n\n logWarn(\n 'SharedModules',\n `No shared module initializer found in bundle for scope=\"${scope.scopedName}\" — falling back to remoteShared mapping`,\n );\n } else {\n logWarn(\n 'SharedModules',\n `No TURBOPACK modules found for scope=\"${scope.scopedName}\" (TURBOPACK_${scope.globalKey} is empty)`,\n );\n }\n\n // fallback: ensure that the shared modules are initialized using remoteShared mapping\n return Promise.all(\n Object.entries(remoteShared).map(async ([id, module]) => {\n if (hostShared[module]) {\n const normalizedId = id.replace('[app-ssr]', '[app-client]');\n scope.sharedModules[normalizedId] = await hostShared[module](\n scope.name,\n );\n } else {\n logError(\n 'SharedModules',\n `Shared module \"${module}\" not found for \"${scope.name}\". ${DEDUPLICATION_WARNING}`,\n );\n }\n }),\n );\n}\n\n/**\n * Extracts shared module IDs from the shared module initializer functions.\n * This parses the minified Turbopack code to find the module ID mappings.\n */\nfunction extractSharedModuleIds(\n shared: Record<string, string | (() => Promise<unknown>)>,\n scope: RemoteScope,\n): Record<string, string> {\n return Object.entries(shared)\n .filter(([, value]) => typeof value === 'function')\n .reduce<Record<string, string>>((acc, [key, value]) => {\n const { asyncSharedModuleId } =\n ASYNC_MODULE_LOADER_RE.exec(value.toString())?.groups ?? {};\n\n if (asyncSharedModuleId) {\n const asyncSharedModuleIdNumber = Number(asyncSharedModuleId);\n\n let asyncSharedModule: (() => unknown) | undefined;\n const turbopackModules = getTurbopackModules(scope) ?? [];\n const asyncSharedModuleIdIndex = turbopackModules.indexOf(\n asyncSharedModuleIdNumber,\n );\n if (\n asyncSharedModuleIdIndex !== -1 &&\n typeof turbopackModules[asyncSharedModuleIdIndex + 1] === 'function'\n ) {\n asyncSharedModule = turbopackModules[\n asyncSharedModuleIdIndex + 1\n ] as () => unknown;\n }\n if (asyncSharedModule) {\n const asyncSharedModuleCode = asyncSharedModule.toString();\n // Try both Promise.resolve and Promise.all patterns\n const { sharedModuleId } =\n ASYNC_MODULE_RESOLVE_RE.exec(asyncSharedModuleCode)?.groups ??\n ASYNC_MODULE_ALL_RE.exec(asyncSharedModuleCode)?.groups ??\n {};\n // map the shared module id to the actual module name\n acc[sharedModuleId ?? asyncSharedModuleId] = key.replace(\n '__remote_shared_module_',\n '',\n );\n }\n }\n return acc;\n }, {});\n}\n\n/**\n * Returns a shared module for the given scope and module ID.\n * Shared modules are common dependencies like React that are provided by the host.\n */\nexport function getSharedModule(\n scope: RemoteScope,\n id: string | number,\n): unknown {\n const idStr = String(id);\n\n // Exact match first (covers both string and numeric IDs)\n if (scope.sharedModules[idStr] !== undefined) {\n return scope.sharedModules[idStr];\n }\n\n // Fallback: the id may be a bundle-prefixed string like \"[bundle] /react/index.js\"\n // that contains the shared module key as a suffix. Only match when the key\n // appears as a complete suffix segment to avoid \"react\" matching \"react-dom\".\n for (const [key, value] of Object.entries(scope.sharedModules)) {\n if (typeof value !== 'undefined' && idStr !== key && idStr.endsWith(key)) {\n return value;\n }\n }\n\n return null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/runtime/turbopack/shared-modules.ts"],"sourcesContent":["import type { GlobalScope } from '#internal/runtime/types';\nimport { logDebug, logError, logWarn } from '#internal/utils/logger';\nimport { findModuleInit, handleTurbopackModule } from './module';\nimport {\n ASYNC_MODULE_CALLBACK_RE,\n ASYNC_MODULE_LOADER_RE,\n extractGroup,\n REMOTE_SHARED_ASSIGNMENT_RE,\n REMOTE_SHARED_MARKER_RE,\n} from './patterns';\nimport { formatRemoteId, type RemoteScope } from './remote-scope';\n\nconst DEDUPLICATION_WARNING =\n 'This module will not be deduplicated — the remote may load its own copy, ' +\n 'which can cause duplicate instance errors (e.g. invalid hook calls if React is loaded twice).';\n\n/**\n * Returns the flat module list for a scope.\n *\n * The primary source is `scope.turbopackModules` — a flat array populated by\n * the push interceptor in handleTurbopackChunk. This is immune to the\n * turbopack runtime replacing the TURBOPACK global (canary builds swap the\n * array for a deferred-loading dispatcher object).\n *\n * Falls back to reading the global for pre-populated bundles where the push\n * interceptor was never installed.\n */\nexport function getTurbopackModules(scope: RemoteScope): unknown[] | undefined {\n if (scope.turbopackModules.length > 0) {\n return scope.turbopackModules;\n }\n\n // Fallback: read the global for pre-populated bundles or legacy setups.\n const self = globalThis as GlobalScope;\n const raw = self[`TURBOPACK_${scope.globalKey}`];\n if (!raw) return undefined;\n\n if (Array.isArray(raw)) {\n return (raw as unknown[]).flat();\n }\n return Object.entries(raw as Record<string, unknown>).flat();\n}\n\n/**\n * Initializes shared modules between the host application and remote components.\n * This enables sharing of common dependencies like React to avoid duplicate instances.\n *\n * The function works by:\n * 1. Looking for a shared module initializer in the Turbopack bundle\n * 2. Extracting module IDs from the initializer\n * 3. Loading the corresponding host modules and mapping them to the remote's expected IDs\n */\nexport async function initializeSharedModules(\n scope: RemoteScope,\n hostShared: Record<string, (bundle?: string) => Promise<unknown>> = {},\n remoteShared: Record<string, string> = {},\n // biome-ignore lint/suspicious/noConfusingVoidType: Runtime is undefined but in TS land service it is void\n): Promise<void[]> {\n const allModules = getTurbopackModules(scope);\n\n logDebug(\n 'SharedModules',\n `initializeSharedModules: scope=\"${scope.scopedName}\", ` +\n `allModules=${allModules ? allModules.length : 'null'}, ` +\n `hostShared=[${Object.keys(hostShared).join(', ')}], ` +\n `remoteShared=${JSON.stringify(remoteShared)}`,\n );\n\n let sharedModuleInitializer: Promise<{\n shared: Record<string, string | (() => Promise<unknown>)>;\n }> | null = null;\n\n // find the shared module initializer in the Turbopack bundle\n if (allModules) {\n // find the shared module initializer module id by looking for\n // a function that contains the TURBOPACK_REMOTE_SHARED pattern\n const sharedModuleInitializerIndex = allModules.findIndex((idOrFunc) => {\n if (typeof idOrFunc !== 'function') {\n return false;\n }\n const funcCode = idOrFunc.toString();\n return REMOTE_SHARED_MARKER_RE.test(funcCode);\n });\n\n // if found, extract the shared module initializer\n // first element in the array is always the source script element\n if (sharedModuleInitializerIndex > 0) {\n const sharedModuleInitializerCode = (\n allModules[sharedModuleInitializerIndex] as () => unknown\n ).toString();\n const sharedModuleInitializerId = allModules[\n sharedModuleInitializerIndex - 1\n ] as string | number;\n // extract the shared module id from the function code\n const sharedModuleId = extractGroup(\n REMOTE_SHARED_ASSIGNMENT_RE,\n sharedModuleInitializerCode,\n 'sharedModuleId',\n );\n // load the shared module initializer using the extracted module id\n if (sharedModuleId) {\n const { default: sharedModuleInitializerInstance } =\n handleTurbopackModule(\n scope,\n sharedModuleId,\n formatRemoteId(scope, String(sharedModuleInitializerId)),\n ) as {\n default: Promise<{\n shared: Record<string, string | (() => Promise<unknown>)>;\n }>;\n };\n sharedModuleInitializer = sharedModuleInitializerInstance;\n }\n }\n\n // if we have a shared module initializer, load the shared modules from the host application\n if (sharedModuleInitializer) {\n const { shared } = await sharedModuleInitializer;\n // map shared module ids to their initializer functions\n const sharedModuleIds = extractSharedModuleIds(shared, scope);\n logDebug(\n 'SharedModules',\n `Resolved shared modules for scope=\"${scope.scopedName}\": ${JSON.stringify(sharedModuleIds)}`,\n );\n\n // load shared modules from the host application\n return Promise.all(\n Object.entries(sharedModuleIds).map(async ([id, module]) => {\n if (hostShared[module]) {\n scope.sharedModules[id] = await hostShared[module](scope.name);\n } else {\n logError(\n 'SharedModules',\n `Host shared module \"${module}\" not found for ID ${id}. ${DEDUPLICATION_WARNING}`,\n );\n }\n }),\n );\n }\n\n logWarn(\n 'SharedModules',\n `No shared module initializer found in bundle for scope=\"${scope.scopedName}\" — falling back to remoteShared mapping`,\n );\n } else {\n logWarn(\n 'SharedModules',\n `No TURBOPACK modules found for scope=\"${scope.scopedName}\" (TURBOPACK_${scope.globalKey} is empty)`,\n );\n }\n\n // fallback: ensure that the shared modules are initialized using remoteShared mapping\n return Promise.all(\n Object.entries(remoteShared).map(async ([id, module]) => {\n if (hostShared[module]) {\n const normalizedId = id.replace('[app-ssr]', '[app-client]');\n scope.sharedModules[normalizedId] = await hostShared[module](\n scope.name,\n );\n } else {\n logError(\n 'SharedModules',\n `Shared module \"${module}\" not found for \"${scope.name}\". ${DEDUPLICATION_WARNING}`,\n );\n }\n }),\n );\n}\n\n/**\n * Extracts shared module IDs from the shared module initializer functions.\n * This parses the minified Turbopack code to find the module ID mappings.\n */\nfunction extractSharedModuleIds(\n shared: Record<string, string | (() => Promise<unknown>)>,\n scope: RemoteScope,\n): Record<string, string> {\n return Object.entries(shared)\n .filter(([, value]) => typeof value === 'function')\n .reduce<Record<string, string>>((acc, [key, value]) => {\n const asyncSharedModuleId = extractGroup(\n ASYNC_MODULE_LOADER_RE,\n value.toString(),\n 'asyncSharedModuleId',\n );\n\n if (asyncSharedModuleId) {\n const asyncSharedModule = findModuleInit(\n getTurbopackModules(scope),\n asyncSharedModuleId,\n );\n if (asyncSharedModule) {\n const sharedModuleId = extractGroup(\n ASYNC_MODULE_CALLBACK_RE,\n asyncSharedModule.toString(),\n 'sharedModuleId',\n );\n // map the shared module id to the actual module name\n acc[sharedModuleId ?? asyncSharedModuleId] = key.replace(\n '__remote_shared_module_',\n '',\n );\n }\n }\n return acc;\n }, {});\n}\n\n/**\n * Returns a shared module for the given scope and module ID.\n * Shared modules are common dependencies like React that are provided by the host.\n */\nexport function getSharedModule(\n scope: RemoteScope,\n id: string | number,\n): unknown {\n const idStr = String(id);\n\n // Exact match first (covers both string and numeric IDs)\n if (scope.sharedModules[idStr] !== undefined) {\n return scope.sharedModules[idStr];\n }\n\n // Fallback: the id may be a bundle-prefixed string like \"[bundle] /react/index.js\"\n // that contains the shared module key as a suffix. Only match when the key\n // appears as a complete suffix segment to avoid \"react\" matching \"react-dom\".\n for (const [key, value] of Object.entries(scope.sharedModules)) {\n if (typeof value !== 'undefined' && idStr !== key && idStr.endsWith(key)) {\n return value;\n }\n }\n\n return null;\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/runtime/types.ts"],"sourcesContent":["import type { RemoteComponentMetadata } from '#internal/runtime/metadata';\n\nexport interface GlobalScope {\n __DISABLE_WEBPACK_EXEC__?: Record<string, boolean>;\n __webpack_chunk_load__?: (\n chunkId: string,\n scriptBundle?: string,\n ) => Promise<unknown> | undefined;\n __original_webpack_chunk_load__?: (\n chunkId: string,\n scriptBundle?: string,\n ) => Promise<unknown> | undefined;\n __webpack_require__?: (id: string) => unknown;\n __webpack_get_script_filename__?: (id: string) => string | null | undefined;\n __original_webpack_require__?: (id: string) => unknown;\n __remote_webpack_require__?: Record<\n string,\n ((remoteId: string | number) => unknown) & {\n c?: Record<\n string | number,\n { id: string; parents: string[]; children: string[] }\n >;\n m?: Record<string | number, (module: { exports: unknown }) => void>;\n type?: 'turbopack' | 'webpack' | 'script';\n }\n >;\n __webpack_require_type__?: RemoteComponentMetadata['runtime'];\n /** Base URL per bundle used by image loaders, HTML host, and webpack plugins. */\n __remote_bundle_url__?: Record<string, string | URL>;\n /** Global chunk dedup cache keyed by absolute URL. */\n __remote_components_turbopack_chunk_loader_promise__?: Record<\n string,\n Promise<unknown>\n >;\n /** RemoteScope registry keyed by scoped name managed by turbopack/remote-scope.ts. */\n __remote_component_scopes__?: Map<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface LoaderResult {\n component: React.ReactNode;\n error?: Error;\n}\n\nexport type RSCKey = `__remote_component_rsc_${string}__`;\n\nexport type MountOrUnmountFunction = (\n el?: ShadowRoot | DocumentFragment | HTMLElement | HTMLCollection | null,\n) => Promise<void> | void;\n\nexport interface MountUnmountFunctions {\n __remote_script_entrypoint_mount__?: Record<\n string,\n Set<MountOrUnmountFunction>\n >;\n __remote_script_entrypoint_unmount__?: Record<\n string,\n Set<MountOrUnmountFunction>\n >;\n}\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
1
+ {"version":3,"sources":["../../../src/runtime/types.ts"],"sourcesContent":["import type { RemoteComponentMetadata } from '#internal/runtime/metadata';\nimport type { RemoteComponentsNamespace } from '#internal/runtime/namespace';\n\nexport interface GlobalScope {\n /** Consolidated namespace — prefer `getNamespace()` over individual globals. */\n __remote_components__?: RemoteComponentsNamespace;\n __DISABLE_WEBPACK_EXEC__?: Record<string, boolean>;\n __webpack_chunk_load__?: (\n chunkId: string,\n scriptBundle?: string,\n ) => Promise<unknown> | undefined;\n __original_webpack_chunk_load__?: (\n chunkId: string,\n scriptBundle?: string,\n ) => Promise<unknown> | undefined;\n __webpack_require__?: (id: string) => unknown;\n __webpack_get_script_filename__?: (id: string) => string | null | undefined;\n __original_webpack_require__?: (id: string) => unknown;\n __remote_webpack_require__?: Record<\n string,\n ((remoteId: string | number) => unknown) & {\n c?: Record<\n string | number,\n { id: string; parents: string[]; children: string[] }\n >;\n m?: Record<string | number, (module: { exports: unknown }) => void>;\n type?: 'turbopack' | 'webpack' | 'script';\n }\n >;\n /** @deprecated since 0.3.4 — use `getNamespace().dispatcherRuntime` instead. */\n __webpack_require_type__?: RemoteComponentMetadata['runtime'];\n /** @deprecated since 0.3.4use `getNamespace().bundleUrls` instead. */\n __remote_bundle_url__?: Record<string, string | URL>;\n /** @deprecated since 0.3.4 use `getNamespace().chunkCache` instead. */\n __remote_components_turbopack_chunk_loader_promise__?: Record<\n string,\n Promise<unknown>\n >;\n /** @deprecated since 0.3.4use `getNamespace().scopes` instead. */\n __remote_component_scopes__?: Map<string, unknown>;\n [key: string]: unknown;\n}\n\nexport interface LoaderResult {\n component: React.ReactNode;\n error?: Error;\n}\n\nexport type RSCKey = `__remote_component_rsc_${string}__`;\n\nexport type MountOrUnmountFunction = (\n el?: ShadowRoot | DocumentFragment | HTMLElement | HTMLCollection | null,\n) => Promise<void> | void;\n\nexport interface MountUnmountFunctions {\n /** @deprecated since 0.3.4 — use `getNamespace().mountFns` instead. */\n __remote_script_entrypoint_mount__?: Record<\n string,\n Set<MountOrUnmountFunction>\n >;\n /** @deprecated since 0.3.4 — use `getNamespace().unmountFns` instead. */\n __remote_script_entrypoint_unmount__?: Record<\n string,\n Set<MountOrUnmountFunction>\n >;\n}\n"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}