@bleedingdev/modern-js-runtime 3.9.0-ultramodern.9 → 3.9.3-ultramodern.2

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 (130) hide show
  1. package/dist/cjs/cli/code.js +2 -2
  2. package/dist/cjs/cli/index.js +0 -7
  3. package/dist/cjs/cli/ssr/loadable-bundler-plugin.js +2 -0
  4. package/dist/cjs/cli/template.server.js +1 -2
  5. package/dist/cjs/core/browser/hydrate.js +3 -9
  6. package/dist/cjs/core/browser/index.js +4 -5
  7. package/dist/cjs/core/context/index.js +8 -2
  8. package/dist/cjs/core/context/public.js +4 -4
  9. package/dist/cjs/core/context/runtime.js +3 -9
  10. package/dist/cjs/core/index.js +3 -3
  11. package/dist/cjs/core/plugin/index.js +2 -2
  12. package/dist/cjs/core/react/index.js +3 -3
  13. package/dist/cjs/core/react/wrapper.js +7 -8
  14. package/dist/cjs/core/server/requestHandler.js +253 -25
  15. package/dist/cjs/core/server/stream/beforeTemplate.js +3 -3
  16. package/dist/cjs/core/server/stream/beforeTemplate.worker.js +2 -2
  17. package/dist/cjs/core/server/stream/createReadableStream.js +51 -19
  18. package/dist/cjs/core/server/stream/createReadableStream.worker.js +54 -27
  19. package/dist/cjs/core/server/stream/deferredScript.js +12 -6
  20. package/dist/cjs/core/server/stream/deferredScriptOutputCoordinator.js +370 -0
  21. package/dist/cjs/core/server/stream/shared.js +4 -0
  22. package/dist/cjs/core/server/string/index.js +6 -4
  23. package/dist/cjs/core/server/string/loadable.js +4 -4
  24. package/dist/cjs/document/cli/index.js +14 -5
  25. package/dist/cjs/exports/head.js +2 -2
  26. package/dist/cjs/internal.js +2 -2
  27. package/dist/cjs/router/cli/code/nestedRoutes.js +1 -2
  28. package/dist/cjs/router/cli/code/templates.js +2 -2
  29. package/dist/cjs/router/cli/code/utils.js +5 -4
  30. package/dist/cjs/router/runtime/DeferredDataScripts.node.js +13 -10
  31. package/dist/cjs/router/runtime/PrefetchLink.js +4 -4
  32. package/dist/cjs/router/runtime/hooks.js +6 -7
  33. package/dist/cjs/router/runtime/plugin.js +22 -27
  34. package/dist/cjs/router/runtime/plugin.node.js +8 -9
  35. package/dist/esm/cli/code.mjs +2 -2
  36. package/dist/esm/cli/index.mjs +0 -7
  37. package/dist/esm/cli/ssr/loadable-bundler-plugin.mjs +2 -0
  38. package/dist/esm/cli/template.server.mjs +1 -2
  39. package/dist/esm/core/browser/hydrate.mjs +3 -9
  40. package/dist/esm/core/browser/index.mjs +1 -2
  41. package/dist/esm/core/context/index.mjs +1 -1
  42. package/dist/esm/core/context/public.mjs +1 -1
  43. package/dist/esm/core/context/runtime.mjs +3 -9
  44. package/dist/esm/core/index.mjs +1 -1
  45. package/dist/esm/core/plugin/index.mjs +1 -1
  46. package/dist/esm/core/react/index.mjs +1 -1
  47. package/dist/esm/core/react/wrapper.mjs +1 -2
  48. package/dist/esm/core/server/requestHandler.mjs +223 -19
  49. package/dist/esm/core/server/stream/beforeTemplate.mjs +3 -3
  50. package/dist/esm/core/server/stream/beforeTemplate.worker.mjs +2 -2
  51. package/dist/esm/core/server/stream/createReadableStream.mjs +48 -16
  52. package/dist/esm/core/server/stream/createReadableStream.worker.mjs +53 -26
  53. package/dist/esm/core/server/stream/deferredScript.mjs +12 -6
  54. package/dist/esm/core/server/stream/deferredScriptOutputCoordinator.mjs +332 -0
  55. package/dist/esm/core/server/stream/shared.mjs +2 -1
  56. package/dist/esm/core/server/string/index.mjs +3 -1
  57. package/dist/esm/core/server/string/loadable.mjs +4 -4
  58. package/dist/esm/document/cli/index.mjs +12 -6
  59. package/dist/esm/exports/head.mjs +1 -1
  60. package/dist/esm/internal.mjs +1 -1
  61. package/dist/esm/router/cli/code/nestedRoutes.mjs +1 -2
  62. package/dist/esm/router/cli/code/templates.mjs +2 -2
  63. package/dist/esm/router/cli/code/utils.mjs +6 -5
  64. package/dist/esm/router/runtime/DeferredDataScripts.node.mjs +13 -10
  65. package/dist/esm/router/runtime/PrefetchLink.mjs +1 -1
  66. package/dist/esm/router/runtime/hooks.mjs +6 -7
  67. package/dist/esm/router/runtime/plugin.mjs +14 -19
  68. package/dist/esm/router/runtime/plugin.node.mjs +3 -4
  69. package/dist/esm-node/cli/code.mjs +2 -2
  70. package/dist/esm-node/cli/index.mjs +1 -9
  71. package/dist/esm-node/cli/ssr/loadable-bundler-plugin.mjs +2 -0
  72. package/dist/esm-node/cli/template.server.mjs +1 -2
  73. package/dist/esm-node/core/browser/hydrate.mjs +3 -9
  74. package/dist/esm-node/core/browser/index.mjs +1 -2
  75. package/dist/esm-node/core/context/index.mjs +1 -1
  76. package/dist/esm-node/core/context/public.mjs +1 -1
  77. package/dist/esm-node/core/context/runtime.mjs +3 -9
  78. package/dist/esm-node/core/index.mjs +1 -1
  79. package/dist/esm-node/core/plugin/index.mjs +1 -1
  80. package/dist/esm-node/core/react/index.mjs +1 -1
  81. package/dist/esm-node/core/react/wrapper.mjs +1 -2
  82. package/dist/esm-node/core/server/requestHandler.mjs +223 -19
  83. package/dist/esm-node/core/server/stream/beforeTemplate.mjs +3 -3
  84. package/dist/esm-node/core/server/stream/beforeTemplate.worker.mjs +2 -2
  85. package/dist/esm-node/core/server/stream/createReadableStream.mjs +48 -16
  86. package/dist/esm-node/core/server/stream/createReadableStream.worker.mjs +53 -26
  87. package/dist/esm-node/core/server/stream/deferredScript.mjs +12 -6
  88. package/dist/esm-node/core/server/stream/deferredScriptOutputCoordinator.mjs +333 -0
  89. package/dist/esm-node/core/server/stream/shared.mjs +2 -1
  90. package/dist/esm-node/core/server/string/index.mjs +3 -1
  91. package/dist/esm-node/core/server/string/loadable.mjs +4 -4
  92. package/dist/esm-node/document/cli/index.mjs +12 -6
  93. package/dist/esm-node/exports/head.mjs +1 -1
  94. package/dist/esm-node/internal.mjs +1 -1
  95. package/dist/esm-node/router/cli/code/nestedRoutes.mjs +1 -2
  96. package/dist/esm-node/router/cli/code/templates.mjs +2 -2
  97. package/dist/esm-node/router/cli/code/utils.mjs +6 -5
  98. package/dist/esm-node/router/runtime/DeferredDataScripts.node.mjs +13 -10
  99. package/dist/esm-node/router/runtime/PrefetchLink.mjs +1 -1
  100. package/dist/esm-node/router/runtime/hooks.mjs +6 -7
  101. package/dist/esm-node/router/runtime/plugin.mjs +14 -19
  102. package/dist/esm-node/router/runtime/plugin.node.mjs +3 -4
  103. package/dist/types/common.d.ts +2 -8
  104. package/dist/types/core/context/index.d.ts +1 -1
  105. package/dist/types/core/context/public.d.ts +1 -1
  106. package/dist/types/core/index.d.ts +1 -1
  107. package/dist/types/core/react/wrapper.d.ts +1 -1
  108. package/dist/types/core/server/requestHandler.d.ts +30 -1
  109. package/dist/types/core/server/stream/deferredScript.d.ts +1 -1
  110. package/dist/types/core/server/stream/deferredScriptOutputCoordinator.d.ts +72 -0
  111. package/dist/types/core/server/stream/shared.d.ts +14 -0
  112. package/dist/types/document/cli/index.d.ts +1 -0
  113. package/dist/types/internal.d.ts +1 -1
  114. package/dist/types/router/cli/code/utils.d.ts +1 -1
  115. package/dist/types/router/runtime/hooks.d.ts +12 -16
  116. package/package.json +32 -26
  117. package/rslib.config.mts +3 -0
  118. package/rstest.config.mts +0 -4
  119. package/dist/cjs/core/server/requestResponse.js +0 -107
  120. package/dist/cjs/core/server/routerCleanup.js +0 -129
  121. package/dist/cjs/rsc/server.worker.js +0 -62
  122. package/dist/esm/core/server/requestResponse.mjs +0 -63
  123. package/dist/esm/core/server/routerCleanup.mjs +0 -82
  124. package/dist/esm/rsc/server.worker.mjs +0 -1
  125. package/dist/esm-node/core/server/requestResponse.mjs +0 -64
  126. package/dist/esm-node/core/server/routerCleanup.mjs +0 -83
  127. package/dist/esm-node/rsc/server.worker.mjs +0 -2
  128. package/dist/types/core/server/requestResponse.d.ts +0 -15
  129. package/dist/types/core/server/routerCleanup.d.ts +0 -31
  130. package/dist/types/rsc/server.worker.d.ts +0 -1
@@ -1,10 +1,10 @@
1
1
  import "node:module";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalIsRscClient, getGlobalLayoutApp, getGlobalRoutes } from "@modern-js/runtime/context";
3
4
  import { merge } from "@modern-js/runtime-utils/merge";
4
5
  import { RouterProvider, createBrowserRouter, createHashRouter, createRoutesFromElements, useHref, useInRouterContext, useLocation, useMatches, useNavigate, useParams } from "@modern-js/runtime-utils/router";
5
6
  import { normalizePathname } from "@modern-js/runtime-utils/url";
6
7
  import * as __rspack_external_react from "react";
7
- import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalIsRscClient, getGlobalLayoutApp, getGlobalRoutes } from "../../core/context/index.mjs";
8
8
  import { routerProviderRegistryHooks } from "./hooks.mjs";
9
9
  import { Link } from "./PrefetchLink.mjs";
10
10
  import { createClientRouterFromPayload } from "./rsc-router.mjs";
@@ -67,24 +67,20 @@ const routerPlugin = (userConfig = {})=>({
67
67
  const match = serverBase.find((baseUrl)=>isSegmentPrefix(pathname, baseUrl));
68
68
  return match || '/';
69
69
  };
70
- let cachedRouter = null;
70
+ const routerCache = new WeakMap();
71
71
  const RouterWrapper = (props)=>{
72
72
  const routerResult = useRouterCreation(("u" > typeof __MODERN_ENABLE_RSC__ ? __MODERN_ENABLE_RSC__ : true === getGlobalEnableRsc()) ? {
73
73
  ...props,
74
74
  rscPayload: props?.rscPayload
75
75
  } : props, {
76
76
  api: api,
77
+ cache: routerCache,
77
78
  createRoutes,
78
79
  supportHtml5History,
79
80
  selectBasePath,
80
81
  basename
81
82
  });
82
- const router = (0, __rspack_external_react.useMemo)(()=>{
83
- if (cachedRouter) return cachedRouter;
84
- cachedRouter = routerResult.router;
85
- return cachedRouter;
86
- }, []);
87
- const { routes } = routerResult;
83
+ const { router, routes } = routerResult;
88
84
  routesContainer.current = routes;
89
85
  beforeCreateRouter = false;
90
86
  const routerContent = /*#__PURE__*/ jsxs(Fragment, {
@@ -121,14 +117,15 @@ function isSegmentPrefix(pathname, base) {
121
117
  return p === b || p.startsWith(`${b}/`);
122
118
  }
123
119
  function useRouterCreation(props, options) {
124
- const { api, createRoutes, supportHtml5History, selectBasePath, basename } = options;
120
+ const { api, cache, createRoutes, supportHtml5History, selectBasePath, basename } = options;
125
121
  const runtimeContext = (0, __rspack_external_react.useContext)(InternalRuntimeContext);
126
122
  const baseUrl = selectBasePath(location.pathname).replace(/^\/*/, '/');
127
123
  const _basename = '/' === baseUrl ? urlJoin(baseUrl, runtimeContext._internalRouterBaseName || basename || '') : baseUrl;
128
124
  const { unstable_getBlockNavState: getBlockNavState } = runtimeContext;
129
125
  const rscPayload = ("u" > typeof __MODERN_ENABLE_RSC__ ? __MODERN_ENABLE_RSC__ : true === getGlobalEnableRsc()) && props?.rscPayload ? safeUse(props.rscPayload) : null;
130
126
  let hydrationData = "u" > typeof __MODERN_ENABLE_RSC__ ? __MODERN_ENABLE_RSC__ ? window._ROUTER_DATA || rscPayload : window._ROUTER_DATA : true === getGlobalEnableRsc() ? window._ROUTER_DATA || rscPayload : window._ROUTER_DATA;
131
- return (0, __rspack_external_react.useMemo)(()=>{
127
+ const result = (0, __rspack_external_react.useRef)(cache.get(runtimeContext) ?? null);
128
+ if (null === result.current) {
132
129
  if (hydrationData?.errors) hydrationData = {
133
130
  ...hydrationData,
134
131
  errors: deserializeErrors(hydrationData.errors)
@@ -144,10 +141,12 @@ function useRouterCreation(props, options) {
144
141
  const hooks = api.getHooks();
145
142
  if (("u" > typeof __MODERN_ENABLE_RSC__ ? __MODERN_ENABLE_RSC__ : true === getGlobalEnableRsc()) && rscPayload) try {
146
143
  const router = createClientRouterFromPayload(rscPayload, routes, _basename);
147
- return {
144
+ result.current = {
148
145
  router,
149
146
  routes: router.routes || []
150
147
  };
148
+ cache.set(runtimeContext, result.current);
149
+ return result.current;
151
150
  } catch (e) {
152
151
  console.error('Failed to create router from RSC payload:', e);
153
152
  }
@@ -196,16 +195,12 @@ function useRouterCreation(props, options) {
196
195
  };
197
196
  return originSubscribe(wrappedListener);
198
197
  };
199
- return {
198
+ result.current = {
200
199
  router,
201
200
  routes: modifiedRoutes
202
201
  };
203
- }, [
204
- finalRouteConfig,
205
- props,
206
- _basename,
207
- hydrationData,
208
- getBlockNavState
209
- ]);
202
+ cache.set(runtimeContext, result.current);
203
+ }
204
+ return result.current;
210
205
  }
211
206
  export { beforeCreateRouter, finalRouteConfig, modifyRoutes, routerPlugin };
@@ -1,12 +1,12 @@
1
1
  import "node:module";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalLayoutApp, getGlobalRoutes } from "@modern-js/runtime/context";
3
4
  import { merge } from "@modern-js/runtime-utils/merge";
4
5
  import { createRequestContext } from "@modern-js/runtime-utils/node";
5
6
  import { StaticRouterProvider, createRoutesFromElements, createStaticHandler, createStaticRouter, useInRouterContext, useLocation, useNavigate, useParams } from "@modern-js/runtime-utils/router";
6
7
  import { time } from "@modern-js/runtime-utils/time";
7
8
  import { LOADER_REPORTER_NAME } from "@modern-js/utils/universal/constants";
8
9
  import { useContext } from "react";
9
- import { InternalRuntimeContext, getGlobalEnableRsc, getGlobalLayoutApp, getGlobalRoutes } from "../../core/context/index.mjs";
10
10
  import { setServerPayload } from "../../core/context/serverPayload/index.server.mjs";
11
11
  import DeferredDataScripts_node from "./DeferredDataScripts.node.mjs";
12
12
  import { routerProviderRegistryHooks } from "./hooks.mjs";
@@ -16,11 +16,10 @@ import { createRouteObjectsFromConfig, renderRoutes, urlJoin } from "./utils.mjs
16
16
  function createRemixRequest(request) {
17
17
  const method = 'GET';
18
18
  const { headers } = request;
19
- const controller = new AbortController();
20
19
  return new Request(request.url, {
21
20
  method,
22
21
  headers,
23
- signal: controller.signal
22
+ signal: request.signal
24
23
  });
25
24
  }
26
25
  const routerPlugin = (userConfig = {})=>({
@@ -124,7 +123,7 @@ const routerPlugin = (userConfig = {})=>({
124
123
  }) : /*#__PURE__*/ jsx(RSCStaticRouter, {
125
124
  basename: basename
126
125
  });
127
- {
126
+ else {
128
127
  const { nonce, mode, useJsonScript } = context.ssrContext;
129
128
  const remixRouter = createStaticRouter(routes, routerContext);
130
129
  const routerWrapper = /*#__PURE__*/ jsxs(Fragment, {
@@ -1,12 +1,6 @@
1
+ import type { RuntimePlugin } from './core/plugin/index.js';
2
+ export type { RuntimePlugin };
1
3
  export declare const isBrowser: () => boolean;
2
- export type RuntimePlugin<Extends = unknown> = {
3
- name?: string;
4
- registryHooks?: Extends extends {
5
- extendHooks: infer Hooks;
6
- } ? Hooks : Record<string, unknown>;
7
- setup?: (...args: any[]) => unknown;
8
- [key: string]: unknown;
9
- };
10
4
  export interface RuntimeConfig {
11
5
  plugins?: RuntimePlugin[];
12
6
  [key: string]: any;
@@ -23,7 +23,7 @@ export { DefaultNotFound } from '../../router/runtime/DefaultNotFound.js';
23
23
  export { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter, type RouterExtendsHooks, type RouterLifecycleContext, routerProviderRegistryHooks, } from '../../router/runtime/hooks.js';
24
24
  export type { LinkPrefetchPolicy } from '../../router/runtime/PrefetchLink.js';
25
25
  export type { LoaderFunction, LoaderFunctionArgs, ModernRoute, } from '../../router/runtime/types.js';
26
- export { getInitialContext, InternalRuntimeContext, RuntimeComponentResolverContext, RuntimeContext, type TInternalRuntimeContext, type TRuntimeContext, } from './runtime.js';
26
+ export { getInitialContext, InternalRuntimeContext, ReactRuntimeContext, type RequestContext, RuntimeComponentResolverContext, RuntimeContext, type TInternalRuntimeContext, type TRuntimeContext, useRuntimeContext, } from './runtime.js';
27
27
  export type { PayloadRoute, ServerPayload } from './serverPayload/index.js';
28
28
  interface GlobalContext {
29
29
  entryName?: string;
@@ -1 +1 @@
1
- export { ReactRuntimeContext, type RequestContext, RuntimeContext, type TRuntimeContext, useRuntimeContext, } from './runtime.js';
1
+ export { ReactRuntimeContext, type RequestContext, RuntimeContext, type TRuntimeContext, useRuntimeContext, } from './index.js';
@@ -1,5 +1,5 @@
1
+ export { RuntimeContext, useRuntimeContext, } from './context/index.js';
1
2
  export { defineRuntimeConfig } from './config.js';
2
3
  export type { TRuntimeContext } from './context/runtime.js';
3
- export { RuntimeContext, useRuntimeContext, } from './context/runtime.js';
4
4
  export type { RuntimePlugin } from './plugin/index.js';
5
5
  export type { SSRContainer, SSRData } from './types.js';
@@ -1,6 +1,6 @@
1
1
  import type { ResolveComponentFn } from '@modern-js/plugin/runtime';
2
- import type React from 'react';
3
2
  import { type TRuntimeContext } from '../context/index.js';
3
+ import type React from 'react';
4
4
  export declare function wrapRuntimeComponentResolver(root: React.ReactNode, hooks?: {
5
5
  resolveComponent?: {
6
6
  call: ResolveComponentFn;
@@ -1,6 +1,35 @@
1
+ import type { SSRRequestRouterResult, SSRRequestTerminal } from '@modern-js/plugin/runtime';
2
+ import { type TInternalRuntimeContext } from '../context/index.js';
1
3
  import type { RequestHandler, RequestHandlerOptions } from '@modern-js/server-core';
4
+ import type { OnError } from '@modern-js/types';
2
5
  import React from 'react';
3
- import { type TInternalRuntimeContext } from '../context/index.js';
6
+ export declare const REQUEST_END_ERROR = "An error occurs during request lifecycle completion";
7
+ export declare const RESPONSE_BODY_CANCEL_ERROR = "An error occurs while cancelling a discarded response body";
8
+ export type RequestLifecycle = {
9
+ /** True once completion belongs to a response body rather than the handler. */
10
+ readonly deferred: boolean;
11
+ /** Notify request completion once; concurrent callers await the same work. */
12
+ run: (terminal?: SSRRequestTerminal) => Promise<void>;
13
+ deferUntilBodyDone: (response: Response) => Response;
14
+ /** Cancel a discarded body before notifying extensions. */
15
+ discardBody: (response: Response, terminal?: SSRRequestTerminal) => Promise<void>;
16
+ };
17
+ export declare function runWithRequestLifecycleOnError<T>(lifecycle: RequestLifecycle, callback: () => Promise<T> | T): Promise<T>;
18
+ export declare function finishWithRequestLifecycle<T>(lifecycle: RequestLifecycle, callback: () => Promise<T> | T): Promise<T>;
19
+ /** The native owner controls body lifetime; plugins own request resources. */
20
+ export declare function createRequestLifecycle(onEnd: (terminal: SSRRequestTerminal) => void | Promise<void>, onError: OnError): RequestLifecycle;
21
+ export type ResponseProxy = {
22
+ headers: Record<string, string>;
23
+ status: number;
24
+ };
25
+ export type RedirectContext = {
26
+ enableRsc: boolean;
27
+ isRSCNavigation: boolean;
28
+ basename: string;
29
+ };
30
+ export declare const applyRouterResult: (context: TInternalRuntimeContext, routerResult: SSRRequestRouterResult | undefined, onError: OnError) => void;
31
+ export declare const createLoaderRedirectResponse: (beforeRenderResult: Response | undefined, redirectCtx: RedirectContext) => Response | undefined;
32
+ export declare const finalizeRenderResponse: (response: Response, responseProxy: ResponseProxy, redirectCtx: RedirectContext, lifecycle: RequestLifecycle) => Promise<Response>;
4
33
  export type { RequestHandlerConfig as HandleRequestConfig } from '@modern-js/server-core';
5
34
  export type HandleRequestOptions = Exclude<RequestHandlerOptions, 'staticGenerate'> & {
6
35
  runtimeContext: TInternalRuntimeContext;
@@ -12,4 +12,4 @@ export declare function toErrorInfo(error: unknown): {
12
12
  stack?: string;
13
13
  };
14
14
  export declare function buildDeferredDataScript(nonce: string | undefined, args: unknown[]): string;
15
- export declare function enqueueFromEntries(entries: Array<[string, unknown]>, nonce: string | undefined, emit: (script: string) => void): void;
15
+ export declare function enqueueFromEntries(entries: Array<[string, unknown]>, deferredScriptKeys: Map<string, string[]> | undefined, nonce: string | undefined, emit: (script: string) => void): Promise<void>;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Serializes the router's deferred-data resolver scripts with React's Fizz
3
+ * output without rewriting either producer's bytes.
4
+ *
5
+ * Why this exists:
6
+ * - A resolver script settles the client-side Promise created for a
7
+ * `defer()` key. It must be sent when that individual server Promise
8
+ * settles; waiting for the whole React stream would unnecessarily delay
9
+ * hydration and interactivity behind unrelated Suspense boundaries.
10
+ * - React and the resolver callbacks are independent stream producers. A
11
+ * direct `write()` can therefore land in a partial HTML tag, a hidden Fizz
12
+ * segment container, or between that container and its continuation
13
+ * instruction.
14
+ * - React's public streaming callbacks expose shell/all-ready lifecycle
15
+ * events, not a safe byte-level insertion point. React chunk sizes and
16
+ * `progressiveChunkSize` are buffering heuristics, not HTML or Fizz
17
+ * boundaries.
18
+ *
19
+ * The coordinator deliberately recognizes the Fizz continuation containers
20
+ * and instructions used by the supported React stream format. This is a
21
+ * compatibility boundary: when the supported React/Fizz output protocol is
22
+ * changed, update this recognizer and its Node, Edge, HTML, SVG, MathML, and
23
+ * table continuation tests together. It is not intended to be a general HTML
24
+ * rewriter.
25
+ *
26
+ * Shell completion only makes a resolver eligible to send. The resolver is
27
+ * emitted after a root-level HTML boundary and, for a continuation segment,
28
+ * after React's matching continuation instruction.
29
+ */
30
+ export declare class DeferredScriptOutputCoordinator {
31
+ private readonly emit;
32
+ private readonly pendingResolvers;
33
+ private readonly openElements;
34
+ private shellFinished;
35
+ private closed;
36
+ private state;
37
+ private currentTagName;
38
+ private currentAttributes;
39
+ private currentAttributeName;
40
+ private currentAttributeValue;
41
+ private currentAttributeHasValue;
42
+ private declarationPrefix;
43
+ private commentTail;
44
+ private rawTextElement;
45
+ private rawTextSearch;
46
+ private continuationProtocolScript;
47
+ private continuationProtocolTail;
48
+ private hasContinuationProtocolCall;
49
+ private awaitingContinuationProtocol;
50
+ constructor(emit: (chunk: string) => void);
51
+ enqueueResolver(script: string): void;
52
+ /**
53
+ * Keep this separate from the ShellChunkStatus assignment. The caller sets
54
+ * FINISH at the existing marker position, then calls this after the marker
55
+ * chunk's afterMark bytes have been observed.
56
+ */
57
+ markShellFinished(): void;
58
+ writeReact(chunk: string): void;
59
+ finish(): void;
60
+ abort(): void;
61
+ private isSafeBoundary;
62
+ private flushResolvers;
63
+ private consume;
64
+ private startTag;
65
+ private startAttribute;
66
+ private completeAttribute;
67
+ private completeStartTag;
68
+ private completeEndTag;
69
+ private consumeRawText;
70
+ private completeRawTextEndTag;
71
+ private closeOpenElement;
72
+ }
@@ -32,6 +32,20 @@ export declare enum ShellChunkStatus {
32
32
  START = 0,
33
33
  FINISH = 1
34
34
  }
35
+ /**
36
+ * The document head is sealed when the shell end mark is written, so only head
37
+ * tags emitted before it reach `<head>`. React writes a completed Suspense
38
+ * boundary after the shell once the flushed bytes exceed `progressiveChunkSize`,
39
+ * which drops the head of every large route and keeps its content hidden until
40
+ * the inline `$RC` script runs. Completed boundaries therefore stay inline in
41
+ * the shell; pending boundaries still stream when they resolve. Buffering
42
+ * paths (`onAllReady`) thereby seal the head after all content.
43
+ *
44
+ * Measured on a ~1 MB route completed at shell time (React 19.3, Node): the
45
+ * default chunk size reaches the shell end mark in 0.7 ms, this one in 1.2 ms,
46
+ * so the head fix costs no measurable time to first byte.
47
+ */
48
+ export declare const SHELL_PROGRESSIVE_CHUNK_SIZE: number;
35
49
  export declare function resolveStreamingMode(request: Request, forceStreamToString: boolean): {
36
50
  onReady: 'onAllReady' | 'onShellReady';
37
51
  waitForAllReady: boolean;
@@ -2,5 +2,6 @@ import type { AppTools, CliPlugin } from '@modern-js/app-tools';
2
2
  import type { Entrypoint } from '@modern-js/types/cli';
3
3
  export declare const processScriptPlaceholders: (html: string, nonce?: string) => string;
4
4
  export declare const getDocumentByEntryName: (entrypoints: Entrypoint[], entryName: string, fallbackDir?: string) => string | undefined;
5
+ export declare const getDocumentTempEntry: (internalDirectory: string, compilerName: string | undefined, entryName: string) => string;
5
6
  export declare const documentPlugin: () => CliPlugin<AppTools>;
6
7
  export default documentPlugin;
@@ -1 +1 @@
1
- export { InternalRuntimeContext, type TInternalRuntimeContext, } from './core/context/runtime.js';
1
+ export { InternalRuntimeContext, type TInternalRuntimeContext, } from './core/context/index.js';
@@ -4,7 +4,7 @@ export declare const replaceWithAlias: (base: string, filePath: string, alias: s
4
4
  export declare const parseModule: ({ source, filename, }: {
5
5
  source: string;
6
6
  filename: string;
7
- }) => Promise<readonly [imports: readonly import("es-module-lexer").ImportSpecifier[], exports: readonly import("es-module-lexer").ExportSpecifier[], facade: boolean, hasModuleSyntax: boolean]>;
7
+ }) => Promise<readonly [imports: readonly import("es-module-lexer").Import[], exports: readonly import("es-module-lexer").Export[], facade: boolean, hasModuleSyntax: boolean]>;
8
8
  export declare const hasLoader: (filename: string, source?: string) => Promise<boolean>;
9
9
  export declare const hasAction: (filename: string, source?: string) => Promise<boolean>;
10
10
  export declare const getServerLoadersFile: (internalDirectory: string, entryName: string) => string;
@@ -10,24 +10,20 @@ export type RouterLifecycleContext = {
10
10
  router?: unknown;
11
11
  [key: string]: unknown;
12
12
  };
13
- export type RouterSyncHook<Handler extends (...args: any[]) => any> = {
14
- call: (...args: Parameters<Handler>) => ReturnType<Handler>;
15
- [key: string]: unknown;
16
- };
17
- declare const modifyRoutes: RouterSyncHook<(routes: RouteObject[]) => RouteObject[]>;
18
- declare const onBeforeCreateRoutes: RouterSyncHook<(context: TRuntimeContext) => void>;
19
- declare const onBeforeCreateRouter: RouterSyncHook<(context: RouterLifecycleContext) => void>;
20
- declare const onAfterCreateRouter: RouterSyncHook<(context: RouterLifecycleContext) => void>;
21
- declare const onBeforeHydrateRouter: RouterSyncHook<(context: RouterLifecycleContext) => void>;
22
- declare const onAfterHydrateRouter: RouterSyncHook<(context: RouterLifecycleContext) => void>;
13
+ declare const modifyRoutes: import("@modern-js/plugin").SyncHook<(routes: RouteObject[]) => RouteObject[]>;
14
+ declare const onBeforeCreateRoutes: import("@modern-js/plugin").SyncHook<(context: TRuntimeContext) => void>;
15
+ declare const onBeforeCreateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
16
+ declare const onAfterCreateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
17
+ declare const onBeforeHydrateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
18
+ declare const onAfterHydrateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
23
19
  export { modifyRoutes, onAfterCreateRouter, onAfterHydrateRouter, onBeforeCreateRouter, onBeforeCreateRoutes, onBeforeHydrateRouter, };
24
20
  export declare const routerProviderRegistryHooks: {
25
- modifyRoutes: RouterSyncHook<(routes: RouteObject[]) => RouteObject[]>;
26
- onBeforeCreateRoutes: RouterSyncHook<(context: TRuntimeContext) => void>;
27
- onBeforeCreateRouter: RouterSyncHook<(context: RouterLifecycleContext) => void>;
28
- onAfterCreateRouter: RouterSyncHook<(context: RouterLifecycleContext) => void>;
29
- onBeforeHydrateRouter: RouterSyncHook<(context: RouterLifecycleContext) => void>;
30
- onAfterHydrateRouter: RouterSyncHook<(context: RouterLifecycleContext) => void>;
21
+ modifyRoutes: import("@modern-js/plugin").SyncHook<(routes: RouteObject[]) => RouteObject[]>;
22
+ onBeforeCreateRoutes: import("@modern-js/plugin").SyncHook<(context: TRuntimeContext) => void>;
23
+ onBeforeCreateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
24
+ onAfterCreateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
25
+ onBeforeHydrateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
26
+ onAfterHydrateRouter: import("@modern-js/plugin").SyncHook<(context: RouterLifecycleContext) => void>;
31
27
  };
32
28
  export type RouterExtendsHooks = {
33
29
  modifyRoutes: typeof modifyRoutes;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@bleedingdev/modern-js-runtime",
3
3
  "description": "A Progressive React Framework for modern web development.",
4
- "homepage": "https://github.com/BleedingDev/ultramodern.js#readme",
4
+ "homepage": "https://github.com/ultramodernjs/ultramodern.js#readme",
5
5
  "bugs": {
6
- "url": "https://github.com/BleedingDev/ultramodern.js/issues"
6
+ "url": "https://github.com/ultramodernjs/ultramodern.js/issues"
7
7
  },
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "git+https://github.com/BleedingDev/ultramodern.js.git",
10
+ "url": "git+https://github.com/ultramodernjs/ultramodern.js.git",
11
11
  "directory": "packages/runtime/plugin-runtime"
12
12
  },
13
13
  "license": "MIT",
@@ -17,7 +17,7 @@
17
17
  "modern",
18
18
  "modern.js"
19
19
  ],
20
- "version": "3.9.0-ultramodern.9",
20
+ "version": "3.9.3-ultramodern.2",
21
21
  "engines": {
22
22
  "node": ">=20"
23
23
  },
@@ -217,50 +217,53 @@
217
217
  "dependencies": {
218
218
  "@loadable/component": "5.16.7",
219
219
  "@loadable/server": "5.16.7",
220
- "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.9",
221
- "@modern-js/plugin-data-loader": "npm:@bleedingdev/modern-js-plugin-data-loader@3.9.0-ultramodern.9",
222
- "@modern-js/render": "npm:@bleedingdev/modern-js-render@3.9.0-ultramodern.9",
223
- "@modern-js/runtime-extensions": "npm:@bleedingdev/modern-js-runtime-extensions@3.9.0-ultramodern.9",
224
- "@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.9.0-ultramodern.9",
225
- "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.9.0-ultramodern.9",
226
- "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.0-ultramodern.9",
227
- "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.9",
228
- "@swc/core": "1.16.2",
220
+ "@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.3-ultramodern.2",
221
+ "@modern-js/plugin-data-loader": "npm:@bleedingdev/modern-js-plugin-data-loader@3.9.3-ultramodern.2",
222
+ "@modern-js/render": "npm:@bleedingdev/modern-js-render@3.9.3-ultramodern.2",
223
+ "@modern-js/runtime-extensions": "npm:@bleedingdev/modern-js-runtime-extensions@3.9.3-ultramodern.2",
224
+ "@modern-js/runtime-renderer-extensions": "npm:@bleedingdev/modern-js-runtime-renderer-extensions@3.9.3-ultramodern.2",
225
+ "@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.9.3-ultramodern.2",
226
+ "@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.9.3-ultramodern.2",
227
+ "@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.3-ultramodern.2",
228
+ "@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.3-ultramodern.2",
229
+ "@rsbuild/plugin-react": "2.1.1",
230
+ "@rsbuild/plugin-svgr": "2.0.5",
231
+ "@swc/core": "1.16.13",
229
232
  "@swc/helpers": "^0.5.23",
230
- "@swc/plugin-loadable-components": "^13.0.0",
233
+ "@swc/plugin-loadable-components": "^14.0.0",
231
234
  "@types/loadable__component": "^5.13.10",
232
235
  "@types/react-helmet": "^6.1.11",
233
236
  "cookie": "2.0.1",
234
- "entities": "^8.0.0",
235
- "es-module-lexer": "^2.3.2",
237
+ "entities": "^8.1.0",
238
+ "es-module-lexer": "^3.0.2",
236
239
  "esbuild": "^0.28.2",
237
240
  "invariant": "^2.2.4",
238
241
  "isbot": "5.2.2",
239
242
  "react-helmet": "^6.1.0",
240
243
  "react-helmet-async": "3.0.0",
241
- "react-is": "^19.2.8"
244
+ "react-is": "^19.3.0",
245
+ "react-router": "7.18.4"
242
246
  },
243
247
  "peerDependencies": {
244
248
  "react": "^19.2.8",
245
249
  "react-dom": "^19.2.8"
246
250
  },
247
251
  "devDependencies": {
248
- "@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.9.0-ultramodern.9",
252
+ "@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.9.3-ultramodern.2",
249
253
  "@remix-run/web-fetch": "^4.4.2",
250
- "@rsbuild/core": "2.2.3",
251
- "@rslib/core": "1.0.0",
254
+ "@rsbuild/core": "2.2.11",
255
+ "@rslib/core": "1.0.3",
252
256
  "@scripts/rstest-config": "2.66.0",
253
- "@testing-library/dom": "^10.4.1",
257
+ "@testing-library/dom": "^10.4.2",
254
258
  "@testing-library/react": "^16.3.3",
255
259
  "@types/cookie": "0.6.0",
256
260
  "@types/invariant": "^2.2.37",
257
261
  "@types/loadable__server": "5.12.11",
258
- "@types/node": "^26.4.1",
259
- "@typescript/native-preview": "7.0.0-dev.20260707.2",
260
- "react": "^19.2.8",
261
- "react-dom": "^19.2.8",
262
+ "@types/node": "^26.6.3",
263
+ "react": "^19.3.0",
264
+ "react-dom": "^19.3.0",
262
265
  "ts-node": "^10.9.2",
263
- "typescript": "^7.0.2"
266
+ "typescript": "7.0.2"
264
267
  },
265
268
  "sideEffects": false,
266
269
  "publishConfig": {
@@ -271,5 +274,8 @@
271
274
  "build": "rslib build && pnpm run gen-static",
272
275
  "gen-static": "node --disable-warning=ExperimentalWarning --experimental-strip-types ./scripts/gen-static.mts",
273
276
  "test": "rstest"
277
+ },
278
+ "ultramodern": {
279
+ "sourceName": "@modern-js/runtime"
274
280
  }
275
281
  }
package/rslib.config.mts CHANGED
@@ -10,6 +10,9 @@ export default defineConfig({
10
10
  },
11
11
  output: {
12
12
  externals: [
13
+ // Keep the package self-reference in the output: Module Federation
14
+ // shares the runtime contexts by that request.
15
+ '@modern-js/runtime/context',
13
16
  {
14
17
  '@modern-js/runtime-utils/node$':
15
18
  'commonjs @modern-js/runtime-utils/node',
package/rstest.config.mts CHANGED
@@ -72,10 +72,6 @@ export default {
72
72
  __dirname,
73
73
  'tests/fixtures/rsc-server.ts',
74
74
  ),
75
- '@modern-js/render/rsc-worker': path.join(
76
- __dirname,
77
- 'tests/fixtures/rsc-server.ts',
78
- ),
79
75
  },
80
76
  },
81
77
  }),
@@ -1,107 +0,0 @@
1
- "use strict";
2
- var __webpack_require__ = {};
3
- (()=>{
4
- __webpack_require__.d = (exports1, getters, values)=>{
5
- var define = (defs, kind)=>{
6
- for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
- enumerable: true,
8
- [kind]: defs[key]
9
- });
10
- };
11
- define(getters, "get");
12
- define(values, "value");
13
- };
14
- })();
15
- (()=>{
16
- __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
- })();
18
- (()=>{
19
- __webpack_require__.r = (exports1)=>{
20
- if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
- value: 'Module'
22
- });
23
- Object.defineProperty(exports1, '__esModule', {
24
- value: true
25
- });
26
- };
27
- })();
28
- var __webpack_exports__ = {};
29
- __webpack_require__.r(__webpack_exports__);
30
- __webpack_require__.d(__webpack_exports__, {
31
- applyRouterSnapshotResult: ()=>applyRouterSnapshotResult,
32
- createLoaderRedirectResponse: ()=>createLoaderRedirectResponse,
33
- finalizeRenderResponse: ()=>finalizeRenderResponse
34
- });
35
- const router_state_namespaceObject = require("@modern-js/runtime-extensions/router-state");
36
- const redirect_js_namespaceObject = require("../../router/runtime/redirect.js");
37
- const external_tracer_js_namespaceObject = require("./tracer.js");
38
- const isRedirectStatus = (status)=>301 === status || 302 === status || 303 === status || 307 === status || 308 === status;
39
- const isNullBodyStatus = (status)=>204 === status || 205 === status || 304 === status;
40
- const getRedirectLocation = (headers)=>{
41
- const location = headers.get('Location');
42
- return null !== location && '' !== location && URL.canParse(location, 'http://localhost') ? location : void 0;
43
- };
44
- const processRedirect = (headers, status, ctx)=>{
45
- headers.delete('content-length');
46
- headers.delete('transfer-encoding');
47
- if (ctx.enableRsc && ctx.isRSCNavigation) return (0, redirect_js_namespaceObject.handleRSCRedirect)(headers, ctx.basename, status);
48
- return new Response(null, {
49
- status,
50
- headers
51
- });
52
- };
53
- const applyRouterSnapshotResult = (context, onError)=>{
54
- const routerServerSnapshot = (0, router_state_namespaceObject.getRouterServerSnapshot)(context);
55
- const routerStatusCode = routerServerSnapshot?.statusCode ?? context.routerContext?.statusCode;
56
- if (void 0 !== routerStatusCode && 0 !== routerStatusCode && !Number.isNaN(routerStatusCode) && 200 !== routerStatusCode) context.ssrContext?.response.status(routerStatusCode);
57
- const errors = Object.values(routerServerSnapshot?.errors || context.routerContext?.errors || {});
58
- if (errors.length > 0) onError(errors[0], external_tracer_js_namespaceObject.SSRErrors.LOADER_ERROR);
59
- };
60
- const createLoaderRedirectResponse = (beforeRenderResult, redirectCtx)=>{
61
- if (void 0 === beforeRenderResult || !isRedirectStatus(beforeRenderResult.status)) return;
62
- if (beforeRenderResult.headers.has('X-Modernjs-Redirect')) return beforeRenderResult;
63
- const redirectUrl = getRedirectLocation(beforeRenderResult.headers);
64
- if (void 0 === redirectUrl) return;
65
- return processRedirect(new Headers(beforeRenderResult.headers), beforeRenderResult.status, redirectCtx);
66
- };
67
- const finalizeRenderResponse = async (response, responseProxy, redirectCtx, routerCleanup)=>{
68
- const proxyHeaders = new Headers(responseProxy.headers);
69
- if (-1 !== responseProxy.status && isRedirectStatus(responseProxy.status) && void 0 !== getRedirectLocation(proxyHeaders)) {
70
- await routerCleanup.discardBody(response);
71
- return processRedirect(proxyHeaders, responseProxy.status, redirectCtx);
72
- }
73
- const headers = new Headers(response.headers);
74
- Object.entries(responseProxy.headers).forEach(([key, value])=>{
75
- headers.set(key, value);
76
- });
77
- if (-1 !== responseProxy.status) {
78
- if (isNullBodyStatus(responseProxy.status)) {
79
- await routerCleanup.discardBody(response);
80
- headers.delete('content-length');
81
- headers.delete('transfer-encoding');
82
- return new Response(null, {
83
- status: responseProxy.status,
84
- headers
85
- });
86
- }
87
- return routerCleanup.deferUntilBodyDone(new Response(response.body, {
88
- status: responseProxy.status,
89
- headers
90
- }));
91
- }
92
- Object.entries(responseProxy.headers).forEach(([key, value])=>{
93
- response.headers.set(key, value);
94
- });
95
- return routerCleanup.deferUntilBodyDone(response);
96
- };
97
- exports.applyRouterSnapshotResult = __webpack_exports__.applyRouterSnapshotResult;
98
- exports.createLoaderRedirectResponse = __webpack_exports__.createLoaderRedirectResponse;
99
- exports.finalizeRenderResponse = __webpack_exports__.finalizeRenderResponse;
100
- for(var __rspack_i in __webpack_exports__)if (-1 === [
101
- "applyRouterSnapshotResult",
102
- "createLoaderRedirectResponse",
103
- "finalizeRenderResponse"
104
- ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
105
- Object.defineProperty(exports, '__esModule', {
106
- value: true
107
- });