@next-core/runtime 1.36.0 → 1.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/cjs/createRoot.js +2 -5
  2. package/dist/cjs/createRoot.js.map +1 -1
  3. package/dist/cjs/internal/Renderer.js +74 -35
  4. package/dist/cjs/internal/Renderer.js.map +1 -1
  5. package/dist/cjs/internal/RendererContext.js +76 -48
  6. package/dist/cjs/internal/RendererContext.js.map +1 -1
  7. package/dist/cjs/internal/Router.js +5 -3
  8. package/dist/cjs/internal/Router.js.map +1 -1
  9. package/dist/cjs/internal/interfaces.js.map +1 -1
  10. package/dist/cjs/internal/poll.js +10 -2
  11. package/dist/cjs/internal/poll.js.map +1 -1
  12. package/dist/cjs/internal/secret_internals.js +1 -1
  13. package/dist/cjs/internal/secret_internals.js.map +1 -1
  14. package/dist/cjs/internal/setupRootRuntimeContext.js +10 -10
  15. package/dist/cjs/internal/setupRootRuntimeContext.js.map +1 -1
  16. package/dist/esm/createRoot.js +2 -5
  17. package/dist/esm/createRoot.js.map +1 -1
  18. package/dist/esm/internal/Renderer.js +84 -45
  19. package/dist/esm/internal/Renderer.js.map +1 -1
  20. package/dist/esm/internal/RendererContext.js +76 -46
  21. package/dist/esm/internal/RendererContext.js.map +1 -1
  22. package/dist/esm/internal/Router.js +5 -3
  23. package/dist/esm/internal/Router.js.map +1 -1
  24. package/dist/esm/internal/interfaces.js.map +1 -1
  25. package/dist/esm/internal/poll.js +10 -2
  26. package/dist/esm/internal/poll.js.map +1 -1
  27. package/dist/esm/internal/secret_internals.js +1 -1
  28. package/dist/esm/internal/secret_internals.js.map +1 -1
  29. package/dist/esm/internal/setupRootRuntimeContext.js +10 -10
  30. package/dist/esm/internal/setupRootRuntimeContext.js.map +1 -1
  31. package/dist/types/internal/Renderer.d.ts +7 -7
  32. package/dist/types/internal/RendererContext.d.ts +8 -7
  33. package/dist/types/internal/interfaces.d.ts +7 -1
  34. package/dist/types/internal/setupRootRuntimeContext.d.ts +1 -1
  35. package/package.json +6 -6
@@ -16,7 +16,6 @@ var _StoryboardFunctions = require("./internal/compute/StoryboardFunctions.js");
16
16
  var _registerAppI18n = require("./internal/registerAppI18n.js");
17
17
  var _registerCustomTemplates = require("./internal/registerCustomTemplates.js");
18
18
  var _setUIVersion = require("./setUIVersion.js");
19
- var _setupRootRuntimeContext = require("./internal/setupRootRuntimeContext.js");
20
19
  function unstable_createRoot(container, {
21
20
  portal: _portal,
22
21
  scope = "fragment",
@@ -71,7 +70,6 @@ function unstable_createRoot(container, {
71
70
  };
72
71
  if (scope === "page") {
73
72
  var _clearI18nBundles;
74
- (0, _setupRootRuntimeContext.setupRootRuntimeContext)(bricks, runtimeContext);
75
73
  (0, _themeAndMode.setTheme)(theme !== null && theme !== void 0 ? theme : "light");
76
74
  (0, _themeAndMode.setMode)("default");
77
75
  (0, _setUIVersion.setUIVersion)(uiVersion);
@@ -103,7 +101,7 @@ function unstable_createRoot(container, {
103
101
  let output;
104
102
  let stores = [];
105
103
  try {
106
- output = await (0, _Renderer.renderBricks)(renderRoot, bricks, runtimeContext, rendererContext, []);
104
+ output = await (0, _Renderer.renderBricks)(renderRoot, bricks, runtimeContext, rendererContext, [], {});
107
105
  stores = (0, _Renderer.getDataStores)(runtimeContext);
108
106
  await (0, _Renderer.postAsyncRender)(output, runtimeContext, stores);
109
107
  } catch (error) {
@@ -118,8 +116,7 @@ function unstable_createRoot(container, {
118
116
  return: renderRoot,
119
117
  runtimeContext: null
120
118
  },
121
- blockingList: [],
122
- menuRequests: []
119
+ blockingList: []
123
120
  };
124
121
  }
125
122
  renderRoot.child = output.node;
@@ -1 +1 @@
1
- {"version":3,"file":"createRoot.js","names":["_lodash","require","_Renderer","_RendererContext","_DataStore","_mount","_handleHttpError","_themeAndMode","_enums","_StoryboardFunctions","_registerAppI18n","_registerCustomTemplates","_setUIVersion","_setupRootRuntimeContext","unstable_createRoot","container","portal","_portal","scope","unknownBricks","createPortal","document","createElement","style","position","width","height","body","append","unmounted","rendererContext","clearI18nBundles","render","brick","theme","uiVersion","context","functions","templates","i18n","i18nData","Error","bricks","concat","previousRendererContext","renderId","uniqueId","RendererContext","runtimeContext","ctxStore","DataStore","undefined","pendingPermissionsPreCheck","tplStateStoreMap","Map","formStateStoreMap","renderRoot","tag","RenderTag","ROOT","_clearI18nBundles","setupRootRuntimeContext","setTheme","setMode","setUIVersion","demoApp","id","homepage","app","demoStoryboard","meta","customTemplates","registerAppI18n","registerCustomTemplates","registerStoryboardFunctions","define","failed","output","stores","renderBricks","getDataStores","postAsyncRender","error","node","BRICK","type","properties","textContent","httpErrorToString","return","blockingList","menuRequests","child","dispatchOnUnmount","dispose","unmountTree","dispatchBeforePageLoad","applyTheme","applyMode","mountTree","window","scrollTo","store","mountAsyncData","dispatchPageLoad","dispatchOnMount","initializeScrollIntoView","initializeMediaChange","initializeMessageDispatcher","unmount","remove"],"sources":["../../src/createRoot.ts"],"sourcesContent":["import type {\n BrickConf,\n ContextConf,\n CustomTemplate,\n MetaI18n,\n MicroApp,\n SiteTheme,\n Storyboard,\n StoryboardFunction,\n} from \"@next-core/types\";\nimport { uniqueId } from \"lodash\";\nimport {\n RenderOutput,\n getDataStores,\n postAsyncRender,\n renderBricks,\n} from \"./internal/Renderer.js\";\nimport { RendererContext } from \"./internal/RendererContext.js\";\nimport { DataStore } from \"./internal/data/DataStore.js\";\nimport type { RenderRoot, RuntimeContext } from \"./internal/interfaces.js\";\nimport { mountTree, unmountTree } from \"./internal/mount.js\";\nimport { httpErrorToString } from \"./handleHttpError.js\";\nimport { applyMode, applyTheme, setMode, setTheme } from \"./themeAndMode.js\";\nimport { RenderTag } from \"./internal/enums.js\";\nimport { registerStoryboardFunctions } from \"./internal/compute/StoryboardFunctions.js\";\nimport { registerAppI18n } from \"./internal/registerAppI18n.js\";\nimport { registerCustomTemplates } from \"./internal/registerCustomTemplates.js\";\nimport { setUIVersion } from \"./setUIVersion.js\";\nimport { setupRootRuntimeContext } from \"./internal/setupRootRuntimeContext.js\";\n\nexport interface CreateRootOptions {\n portal?: HTMLElement;\n /**\n * Defaults to \"fragment\", only set it to \"page\" when the root is in a standalone iframe.\n * - page: render as whole page, triggering page life cycles, and enable register of functions/templates/i18n.\n * - fragment: render as fragment, not triggering page life cycles, and disable register of functions/templates/i18n.\n */\n scope?: \"page\" | \"fragment\";\n\n /**\n * Whether to throw error when encountering unknown bricks.\n *\n * Defaults to \"throw\".\n */\n unknownBricks?: \"silent\" | \"throw\";\n}\n\nexport interface RenderOptions {\n theme?: SiteTheme;\n uiVersion?: string;\n context?: ContextConf[];\n functions?: StoryboardFunction[];\n templates?: CustomTemplate[];\n i18n?: MetaI18n;\n}\n\nexport function unstable_createRoot(\n container: HTMLElement | DocumentFragment,\n { portal: _portal, scope = \"fragment\", unknownBricks }: CreateRootOptions = {}\n) {\n let portal = _portal;\n let createPortal: RenderRoot[\"createPortal\"];\n if (_portal) {\n createPortal = _portal;\n } else {\n // Create portal container when necessary.\n createPortal = () => {\n portal = document.createElement(\"div\");\n portal.style.position = \"absolute\";\n portal.style.width = portal.style.height = \"0\";\n document.body.append(portal);\n return portal;\n };\n }\n let unmounted = false;\n let rendererContext: RendererContext | undefined;\n let clearI18nBundles: Function | undefined;\n\n return {\n async render(\n brick: BrickConf | BrickConf[],\n {\n theme,\n uiVersion,\n context,\n functions,\n templates,\n i18n: i18nData,\n }: RenderOptions = {}\n ) {\n if (unmounted) {\n throw new Error(\n \"The root is unmounted and cannot be rendered any more\"\n );\n }\n const bricks = ([] as BrickConf[]).concat(brick);\n\n const previousRendererContext = rendererContext;\n const renderId = uniqueId(\"render-id-\");\n rendererContext = new RendererContext(scope, { unknownBricks, renderId });\n\n const runtimeContext = {\n ctxStore: new DataStore(\"CTX\", undefined, rendererContext),\n pendingPermissionsPreCheck: [],\n tplStateStoreMap: new Map<string, DataStore<\"STATE\">>(),\n formStateStoreMap: new Map<string, DataStore<\"FORM_STATE\">>(),\n } as Partial<RuntimeContext> as RuntimeContext;\n\n const renderRoot: RenderRoot = {\n tag: RenderTag.ROOT,\n container,\n createPortal,\n };\n\n if (scope === \"page\") {\n setupRootRuntimeContext(bricks, runtimeContext);\n setTheme(theme ?? \"light\");\n setMode(\"default\");\n setUIVersion(uiVersion);\n\n const demoApp = {\n id: \"demo\",\n homepage: \"/demo\",\n } as MicroApp;\n runtimeContext.app = demoApp;\n const demoStoryboard = {\n app: demoApp,\n meta: {\n i18n: i18nData,\n customTemplates: templates,\n },\n } as Storyboard;\n\n // Register i18n.\n clearI18nBundles?.();\n clearI18nBundles = registerAppI18n(demoStoryboard);\n\n // Register custom templates.\n registerCustomTemplates(demoStoryboard);\n\n // Register functions.\n registerStoryboardFunctions(functions, demoApp);\n }\n\n runtimeContext.ctxStore.define(context, runtimeContext);\n\n let failed = false;\n let output: RenderOutput;\n let stores: DataStore<\"CTX\" | \"STATE\" | \"FORM_STATE\">[] = [];\n\n try {\n output = await renderBricks(\n renderRoot,\n bricks,\n runtimeContext,\n rendererContext,\n []\n );\n\n stores = getDataStores(runtimeContext);\n await postAsyncRender(output, runtimeContext, stores);\n } catch (error) {\n failed = true;\n output = {\n node: {\n tag: RenderTag.BRICK,\n type: \"div\",\n properties: {\n textContent: httpErrorToString(error),\n },\n return: renderRoot,\n runtimeContext: null!,\n },\n blockingList: [],\n menuRequests: [],\n };\n }\n\n renderRoot.child = output.node;\n\n previousRendererContext?.dispatchOnUnmount();\n previousRendererContext?.dispose();\n unmountTree(container);\n if (portal) {\n unmountTree(portal);\n }\n\n if (scope === \"page\") {\n if (!failed) {\n rendererContext.dispatchBeforePageLoad();\n }\n\n applyTheme();\n applyMode();\n }\n\n mountTree(renderRoot);\n\n if (scope === \"page\") {\n window.scrollTo(0, 0);\n }\n\n if (!failed) {\n for (const store of stores) {\n store.mountAsyncData();\n }\n\n if (scope === \"page\") {\n rendererContext.dispatchPageLoad();\n // rendererContext.dispatchAnchorLoad();\n }\n rendererContext.dispatchOnMount();\n rendererContext.initializeScrollIntoView();\n rendererContext.initializeMediaChange();\n rendererContext.initializeMessageDispatcher();\n }\n },\n unmount() {\n if (unmounted) {\n return;\n }\n unmounted = true;\n unmountTree(container);\n if (portal) {\n unmountTree(portal);\n // Only remove the portal from its parent when it's dynamic created.\n if (!_portal) {\n portal.remove();\n }\n }\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createRoot.js","names":["_lodash","require","_Renderer","_RendererContext","_DataStore","_mount","_handleHttpError","_themeAndMode","_enums","_StoryboardFunctions","_registerAppI18n","_registerCustomTemplates","_setUIVersion","unstable_createRoot","container","portal","_portal","scope","unknownBricks","createPortal","document","createElement","style","position","width","height","body","append","unmounted","rendererContext","clearI18nBundles","render","brick","theme","uiVersion","context","functions","templates","i18n","i18nData","Error","bricks","concat","previousRendererContext","renderId","uniqueId","RendererContext","runtimeContext","ctxStore","DataStore","undefined","pendingPermissionsPreCheck","tplStateStoreMap","Map","formStateStoreMap","renderRoot","tag","RenderTag","ROOT","_clearI18nBundles","setTheme","setMode","setUIVersion","demoApp","id","homepage","app","demoStoryboard","meta","customTemplates","registerAppI18n","registerCustomTemplates","registerStoryboardFunctions","define","failed","output","stores","renderBricks","getDataStores","postAsyncRender","error","node","BRICK","type","properties","textContent","httpErrorToString","return","blockingList","child","dispatchOnUnmount","dispose","unmountTree","dispatchBeforePageLoad","applyTheme","applyMode","mountTree","window","scrollTo","store","mountAsyncData","dispatchPageLoad","dispatchOnMount","initializeScrollIntoView","initializeMediaChange","initializeMessageDispatcher","unmount","remove"],"sources":["../../src/createRoot.ts"],"sourcesContent":["import type {\n BrickConf,\n ContextConf,\n CustomTemplate,\n MetaI18n,\n MicroApp,\n SiteTheme,\n Storyboard,\n StoryboardFunction,\n} from \"@next-core/types\";\nimport { uniqueId } from \"lodash\";\nimport {\n RenderOutput,\n getDataStores,\n postAsyncRender,\n renderBricks,\n} from \"./internal/Renderer.js\";\nimport { RendererContext } from \"./internal/RendererContext.js\";\nimport { DataStore } from \"./internal/data/DataStore.js\";\nimport type { RenderRoot, RuntimeContext } from \"./internal/interfaces.js\";\nimport { mountTree, unmountTree } from \"./internal/mount.js\";\nimport { httpErrorToString } from \"./handleHttpError.js\";\nimport { applyMode, applyTheme, setMode, setTheme } from \"./themeAndMode.js\";\nimport { RenderTag } from \"./internal/enums.js\";\nimport { registerStoryboardFunctions } from \"./internal/compute/StoryboardFunctions.js\";\nimport { registerAppI18n } from \"./internal/registerAppI18n.js\";\nimport { registerCustomTemplates } from \"./internal/registerCustomTemplates.js\";\nimport { setUIVersion } from \"./setUIVersion.js\";\n\nexport interface CreateRootOptions {\n portal?: HTMLElement;\n /**\n * Defaults to \"fragment\", only set it to \"page\" when the root is in a standalone iframe.\n * - page: render as whole page, triggering page life cycles, and enable register of functions/templates/i18n.\n * - fragment: render as fragment, not triggering page life cycles, and disable register of functions/templates/i18n.\n */\n scope?: \"page\" | \"fragment\";\n\n /**\n * Whether to throw error when encountering unknown bricks.\n *\n * Defaults to \"throw\".\n */\n unknownBricks?: \"silent\" | \"throw\";\n}\n\nexport interface RenderOptions {\n theme?: SiteTheme;\n uiVersion?: string;\n context?: ContextConf[];\n functions?: StoryboardFunction[];\n templates?: CustomTemplate[];\n i18n?: MetaI18n;\n}\n\nexport function unstable_createRoot(\n container: HTMLElement | DocumentFragment,\n { portal: _portal, scope = \"fragment\", unknownBricks }: CreateRootOptions = {}\n) {\n let portal = _portal;\n let createPortal: RenderRoot[\"createPortal\"];\n if (_portal) {\n createPortal = _portal;\n } else {\n // Create portal container when necessary.\n createPortal = () => {\n portal = document.createElement(\"div\");\n portal.style.position = \"absolute\";\n portal.style.width = portal.style.height = \"0\";\n document.body.append(portal);\n return portal;\n };\n }\n let unmounted = false;\n let rendererContext: RendererContext | undefined;\n let clearI18nBundles: Function | undefined;\n\n return {\n async render(\n brick: BrickConf | BrickConf[],\n {\n theme,\n uiVersion,\n context,\n functions,\n templates,\n i18n: i18nData,\n }: RenderOptions = {}\n ) {\n if (unmounted) {\n throw new Error(\n \"The root is unmounted and cannot be rendered any more\"\n );\n }\n const bricks = ([] as BrickConf[]).concat(brick);\n\n const previousRendererContext = rendererContext;\n const renderId = uniqueId(\"render-id-\");\n rendererContext = new RendererContext(scope, { unknownBricks, renderId });\n\n const runtimeContext = {\n ctxStore: new DataStore(\"CTX\", undefined, rendererContext),\n pendingPermissionsPreCheck: [],\n tplStateStoreMap: new Map<string, DataStore<\"STATE\">>(),\n formStateStoreMap: new Map<string, DataStore<\"FORM_STATE\">>(),\n } as Partial<RuntimeContext> as RuntimeContext;\n\n const renderRoot: RenderRoot = {\n tag: RenderTag.ROOT,\n container,\n createPortal,\n };\n\n if (scope === \"page\") {\n setTheme(theme ?? \"light\");\n setMode(\"default\");\n setUIVersion(uiVersion);\n\n const demoApp = {\n id: \"demo\",\n homepage: \"/demo\",\n } as MicroApp;\n runtimeContext.app = demoApp;\n const demoStoryboard = {\n app: demoApp,\n meta: {\n i18n: i18nData,\n customTemplates: templates,\n },\n } as Storyboard;\n\n // Register i18n.\n clearI18nBundles?.();\n clearI18nBundles = registerAppI18n(demoStoryboard);\n\n // Register custom templates.\n registerCustomTemplates(demoStoryboard);\n\n // Register functions.\n registerStoryboardFunctions(functions, demoApp);\n }\n\n runtimeContext.ctxStore.define(context, runtimeContext);\n\n let failed = false;\n let output: RenderOutput;\n let stores: DataStore<\"CTX\" | \"STATE\" | \"FORM_STATE\">[] = [];\n\n try {\n output = await renderBricks(\n renderRoot,\n bricks,\n runtimeContext,\n rendererContext,\n [],\n {}\n );\n\n stores = getDataStores(runtimeContext);\n await postAsyncRender(output, runtimeContext, stores);\n } catch (error) {\n failed = true;\n output = {\n node: {\n tag: RenderTag.BRICK,\n type: \"div\",\n properties: {\n textContent: httpErrorToString(error),\n },\n return: renderRoot,\n runtimeContext: null!,\n },\n blockingList: [],\n };\n }\n\n renderRoot.child = output.node;\n\n previousRendererContext?.dispatchOnUnmount();\n previousRendererContext?.dispose();\n unmountTree(container);\n if (portal) {\n unmountTree(portal);\n }\n\n if (scope === \"page\") {\n if (!failed) {\n rendererContext.dispatchBeforePageLoad();\n }\n\n applyTheme();\n applyMode();\n }\n\n mountTree(renderRoot);\n\n if (scope === \"page\") {\n window.scrollTo(0, 0);\n }\n\n if (!failed) {\n for (const store of stores) {\n store.mountAsyncData();\n }\n\n if (scope === \"page\") {\n rendererContext.dispatchPageLoad();\n // rendererContext.dispatchAnchorLoad();\n }\n rendererContext.dispatchOnMount();\n rendererContext.initializeScrollIntoView();\n rendererContext.initializeMediaChange();\n rendererContext.initializeMessageDispatcher();\n }\n },\n unmount() {\n if (unmounted) {\n return;\n }\n unmounted = true;\n unmountTree(container);\n if (portal) {\n unmountTree(portal);\n // Only remove the portal from its parent when it's dynamic created.\n if (!_portal) {\n portal.remove();\n }\n }\n },\n };\n}\n"],"mappings":"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"}
@@ -34,9 +34,14 @@ var _expandFormRenderer = require("./FormRenderer/expandFormRenderer.js");
34
34
  var _evaluate = require("./compute/evaluate.js");
35
35
  var _matchStoryboard = require("./matchStoryboard.js");
36
36
  var _bindListeners = require("./bindListeners.js");
37
- async function renderRoutes(returnNode, routes, _runtimeContext, rendererContext, parentRoutes, slotId, isIncremental) {
37
+ var _setupRootRuntimeContext = require("./setupRootRuntimeContext.js");
38
+ async function renderRoutes(returnNode, routes, _runtimeContext, rendererContext, parentRoutes, menuRequestReturnNode, slotId, isIncremental) {
38
39
  const matched = await (0, _matchRoutes.matchRoutes)(routes, _runtimeContext);
39
40
  const output = getEmptyRenderOutput();
41
+ const menuRequestNode = {
42
+ return: menuRequestReturnNode
43
+ };
44
+ output.menuRequestNode = menuRequestNode;
40
45
  switch (matched) {
41
46
  case "missed":
42
47
  break;
@@ -89,28 +94,30 @@ async function renderRoutes(returnNode, routes, _runtimeContext, rendererContext
89
94
  } else {
90
95
  const menuRequest = loadMenu(route.menu, runtimeContext);
91
96
  if (menuRequest) {
92
- output.menuRequests.push(menuRequest);
97
+ menuRequestNode.request = menuRequest;
98
+ }
99
+ if (!isIncremental) {
100
+ rendererContext.memoizeMenuRequestNode(routes, menuRequestNode);
93
101
  }
102
+ let newOutput;
94
103
  if (route.type === "routes") {
95
- const newOutput = await renderRoutes(returnNode, route.routes, runtimeContext, rendererContext, routePath, slotId);
96
- mergeRenderOutput(output, newOutput);
104
+ newOutput = await renderRoutes(returnNode, route.routes, runtimeContext, rendererContext, routePath, menuRequestNode, slotId);
97
105
  } else {
98
- const newOutput = await renderBricks(returnNode, route.bricks, runtimeContext, rendererContext, routePath, slotId);
99
- mergeRenderOutput(output, newOutput);
100
- }
101
- if (returnNode.tag === _enums.RenderTag.BRICK) {
102
- rendererContext.memoizeMenuRequests(route, output.menuRequests);
106
+ newOutput = await renderBricks(returnNode, route.bricks, runtimeContext, rendererContext, routePath, menuRequestNode, slotId);
103
107
  }
108
+ mergeRenderOutput(output, newOutput);
109
+ appendMenuRequestNode(menuRequestReturnNode, newOutput.menuRequestNode);
104
110
  }
105
111
  }
106
112
  }
107
113
  return output;
108
114
  }
109
- async function renderBricks(returnNode, bricks, runtimeContext, rendererContext, parentRoutes, slotId, tplStack, keyPath) {
115
+ async function renderBricks(returnNode, bricks, runtimeContext, rendererContext, parentRoutes, menuRequestReturnNode, slotId, tplStack, keyPath) {
116
+ (0, _setupRootRuntimeContext.setupRootRuntimeContext)(bricks, runtimeContext, true);
110
117
  const output = getEmptyRenderOutput();
111
118
  const kPath = keyPath !== null && keyPath !== void 0 ? keyPath : [];
112
119
  // 多个构件并行异步转换,但转换的结果按原顺序串行合并。
113
- const rendered = await Promise.all(bricks.map((brickConf, index) => renderBrick(returnNode, brickConf, runtimeContext, rendererContext, parentRoutes, slotId, kPath.concat(index), tplStack && new Map(tplStack))));
120
+ const rendered = await Promise.all(bricks.map((brickConf, index) => renderBrick(returnNode, brickConf, runtimeContext, rendererContext, parentRoutes, menuRequestReturnNode, slotId, kPath.concat(index), tplStack && new Map(tplStack))));
114
121
  rendered.forEach((item, index) => {
115
122
  if (item.hasTrackingControls) {
116
123
  // Memoize a render node before it's been merged.
@@ -120,7 +127,7 @@ async function renderBricks(returnNode, bricks, runtimeContext, rendererContext,
120
127
  });
121
128
  return output;
122
129
  }
123
- async function renderBrick(returnNode, brickConf, _runtimeContext, rendererContext, parentRoutes, slotId, keyPath = [], tplStack = new Map()) {
130
+ async function renderBrick(returnNode, brickConf, _runtimeContext, rendererContext, parentRoutes, menuRequestReturnNode, slotId, keyPath = [], tplStack = new Map()) {
124
131
  var _hooks$checkPermissio2, _runtimeContext$app;
125
132
  const output = getEmptyRenderOutput();
126
133
  if (!brickConf.brick) {
@@ -158,7 +165,7 @@ async function renderBrick(returnNode, brickConf, _runtimeContext, rendererConte
158
165
  ...acc,
159
166
  [symbol]: brickConf[symbol]
160
167
  }), {})
161
- }, _runtimeContext, rendererContext, parentRoutes, slotId, keyPath, tplStack);
168
+ }, _runtimeContext, rendererContext, parentRoutes, menuRequestReturnNode, slotId, keyPath, tplStack);
162
169
  }
163
170
  const tplStateStoreId = brickConf[_constants.symbolForTplStateStoreId];
164
171
  const formStateStoreId = brickConf[_constants2.symbolForFormStateStoreId];
@@ -220,12 +227,12 @@ async function renderBrick(returnNode, brickConf, _runtimeContext, rendererConte
220
227
  if (!Array.isArray(computedDataSource)) {
221
228
  return getEmptyRenderOutput();
222
229
  }
223
- return renderForEach(returnNode, computedDataSource, bricks, runtimeContext, rendererContext, parentRoutes, slotId, tplStack, keyPath);
230
+ return renderForEach(returnNode, computedDataSource, bricks, runtimeContext, rendererContext, parentRoutes, menuRequestReturnNode, slotId, tplStack, keyPath);
224
231
  }
225
232
  case ":if":
226
233
  case ":switch":
227
234
  {
228
- return renderBricks(returnNode, bricks, runtimeContext, rendererContext, parentRoutes, slotId, tplStack, keyPath);
235
+ return renderBricks(returnNode, bricks, runtimeContext, rendererContext, parentRoutes, menuRequestReturnNode, slotId, tplStack, keyPath);
229
236
  }
230
237
  }
231
238
  };
@@ -431,12 +438,12 @@ async function renderBrick(returnNode, brickConf, _runtimeContext, rendererConte
431
438
  const routeSlotFromIndexToSlotId = new Map();
432
439
  const rendered = await Promise.all(Object.entries(slots).map(([childSlotId, slotConf], index) => {
433
440
  if (slotConf.type !== "routes") {
434
- return renderBricks(brick, slotConf.bricks, childRuntimeContext, rendererContext, parentRoutes, childSlotId, tplStack);
441
+ return renderBricks(brick, slotConf.bricks, childRuntimeContext, rendererContext, parentRoutes, menuRequestReturnNode, childSlotId, tplStack);
435
442
  }
436
443
  const parentRoute = parentRoutes[parentRoutes.length - 1];
437
444
  if (parentRoute !== null && parentRoute !== void 0 && parentRoute.incrementalSubRoutes) {
438
445
  routeSlotFromIndexToSlotId.set(index, childSlotId);
439
- rendererContext.performIncrementalRender(async (location, prevLocation) => {
446
+ rendererContext.performIncrementalRender(slotConf, parentRoutes, async (location, prevLocation) => {
440
447
  const {
441
448
  homepage
442
449
  } = childRuntimeContext.app;
@@ -460,18 +467,19 @@ async function renderBrick(returnNode, brickConf, _runtimeContext, rendererConte
460
467
  let incrementalOutput;
461
468
  let scopedStores = [];
462
469
  try {
463
- incrementalOutput = await renderRoutes(brick, slotConf.routes, scopedRuntimeContext, rendererContext, parentRoutes, childSlotId, true);
470
+ incrementalOutput = await renderRoutes(brick, slotConf.routes, scopedRuntimeContext, rendererContext, parentRoutes, menuRequestReturnNode, childSlotId, true);
464
471
 
465
472
  // Do not ignore incremental rendering even if all sub-routes are missed.
466
473
  // Since parent route is matched.
467
-
468
- // Bailout if redirect or unauthenticated is set
469
- if (rendererContext.reBailout(incrementalOutput)) {
470
- return true;
474
+ if (incrementalOutput.route) {
475
+ // Bailout if redirect or unauthenticated is set
476
+ if (rendererContext.reBailout(incrementalOutput)) {
477
+ return true;
478
+ }
479
+ scopedStores = [...tplStateStoreScope, ...formStateStoreScope];
480
+ await postAsyncRender(incrementalOutput, scopedRuntimeContext, [scopedRuntimeContext.ctxStore, ...scopedStores]);
471
481
  }
472
- scopedStores = [...tplStateStoreScope, ...formStateStoreScope];
473
- await postAsyncRender(incrementalOutput, scopedRuntimeContext, [scopedRuntimeContext.ctxStore, ...scopedStores]);
474
- await rendererContext.reMergeMenuRequests(slotConf.routes, incrementalOutput.route, incrementalOutput.menuRequests);
482
+ await rendererContext.reMergeMenuRequestNodes(menuRequestReturnNode, slotConf.routes, incrementalOutput.menuRequestNode);
475
483
  } catch (error) {
476
484
  // eslint-disable-next-line no-console
477
485
  console.error("Incremental sub-router failed:", error);
@@ -485,7 +493,7 @@ async function renderBrick(returnNode, brickConf, _runtimeContext, rendererConte
485
493
  } = result);
486
494
 
487
495
  // Assert: no errors will be throw
488
- await rendererContext.reMergeMenuRequests(slotConf.routes, incrementalOutput.route, incrementalOutput.menuRequests);
496
+ await rendererContext.reMergeMenuRequestNodes(menuRequestReturnNode, slotConf.routes, incrementalOutput.menuRequestNode);
489
497
  }
490
498
  rendererContext.reRender(childSlotId, [], incrementalOutput.node, brick);
491
499
  if (!failed) {
@@ -494,16 +502,19 @@ async function renderBrick(returnNode, brickConf, _runtimeContext, rendererConte
494
502
  store.mountAsyncData();
495
503
  }
496
504
  }
497
- return true;
505
+
506
+ // When result is null, it means the incremental rendering is tried but routes missed.
507
+ // In this case, we should continue to re-render the parent routes.
508
+ return incrementalOutput.route ? true : null;
498
509
  });
499
510
  }
500
- return renderRoutes(brick, slotConf.routes, childRuntimeContext, rendererContext, parentRoutes, childSlotId);
511
+ return renderRoutes(brick, slotConf.routes, childRuntimeContext, rendererContext, parentRoutes, menuRequestReturnNode, childSlotId);
501
512
  }));
502
513
  const childrenOutput = {
503
514
  ...output,
504
515
  node: undefined,
505
516
  blockingList: [],
506
- menuRequests: []
517
+ menuRequestNode: undefined
507
518
  };
508
519
  rendered.forEach((item, index) => {
509
520
  if (routeSlotFromIndexToSlotId.has(index)) {
@@ -511,6 +522,7 @@ async function renderBrick(returnNode, brickConf, _runtimeContext, rendererConte
511
522
  rendererContext.memoize(routeSlotFromIndexToSlotId.get(index), [], item.node, brick);
512
523
  }
513
524
  mergeRenderOutput(childrenOutput, item);
525
+ mergeSiblingRenderMenuRequest(childrenOutput, item);
514
526
  });
515
527
  if (childrenOutput.node) {
516
528
  brick.child = childrenOutput.node;
@@ -519,6 +531,7 @@ async function renderBrick(returnNode, brickConf, _runtimeContext, rendererConte
519
531
  ...childrenOutput,
520
532
  node: undefined
521
533
  });
534
+ appendMenuRequestNode(menuRequestReturnNode, output.menuRequestNode = childrenOutput.menuRequestNode);
522
535
  };
523
536
  blockingList.push(loadChildren());
524
537
  await Promise.all(blockingList);
@@ -534,14 +547,14 @@ function ensureValidControlBrick(brick) {
534
547
  throw new Error(`Unknown storyboard control node: "${brick}"`);
535
548
  }
536
549
  }
537
- async function renderForEach(returnNode, dataSource, bricks, runtimeContext, rendererContext, parentRoutes, slotId, tplStack, keyPath) {
550
+ async function renderForEach(returnNode, dataSource, bricks, runtimeContext, rendererContext, parentRoutes, menuRequestReturnNode, slotId, tplStack, keyPath) {
538
551
  const output = getEmptyRenderOutput();
539
552
  const rows = dataSource.length;
540
553
  const rendered = await Promise.all(dataSource.map((item, i) => Promise.all(bricks.map((brickConf, j) => renderBrick(returnNode, brickConf, {
541
554
  ...runtimeContext,
542
555
  forEachItem: item,
543
556
  forEachIndex: i
544
- }, rendererContext, parentRoutes, slotId, keyPath.concat(i * rows + j), tplStack && new Map(tplStack))))));
557
+ }, rendererContext, parentRoutes, menuRequestReturnNode, slotId, keyPath.concat(i * rows + j), tplStack && new Map(tplStack))))));
545
558
 
546
559
  // 多层构件并行异步转换,但转换的结果按原顺序串行合并。
547
560
  rendered.flat().forEach((item, index) => {
@@ -595,12 +608,11 @@ function mergeRenderOutput(output, newOutput) {
595
608
  const {
596
609
  blockingList,
597
610
  node,
598
- menuRequests,
611
+ menuRequestNode,
599
612
  hasTrackingControls,
600
613
  ...rest
601
614
  } = newOutput;
602
615
  output.blockingList.push(...blockingList);
603
- output.menuRequests.push(...menuRequests);
604
616
  if (node) {
605
617
  if (output.node) {
606
618
  let last = output.node;
@@ -614,10 +626,37 @@ function mergeRenderOutput(output, newOutput) {
614
626
  }
615
627
  Object.assign(output, rest);
616
628
  }
629
+ function mergeSiblingRenderMenuRequest(output, newOutput) {
630
+ const menuRequestNode = newOutput.menuRequestNode;
631
+ if (menuRequestNode) {
632
+ if (output.menuRequestNode) {
633
+ let last = output.menuRequestNode;
634
+ while (last.sibling) {
635
+ last = last.sibling;
636
+ }
637
+ last.sibling = menuRequestNode;
638
+ } else {
639
+ output.menuRequestNode = menuRequestNode;
640
+ }
641
+ }
642
+ }
643
+ function appendMenuRequestNode(menuRequestReturnNode, menuRequestNode) {
644
+ if (!menuRequestNode) {
645
+ return;
646
+ }
647
+ if (menuRequestReturnNode.child) {
648
+ let last = menuRequestReturnNode.child;
649
+ while (last.sibling) {
650
+ last = last.sibling;
651
+ }
652
+ last.sibling = menuRequestNode;
653
+ } else {
654
+ menuRequestReturnNode.child = menuRequestNode;
655
+ }
656
+ }
617
657
  function getEmptyRenderOutput() {
618
658
  return {
619
- blockingList: [],
620
- menuRequests: []
659
+ blockingList: []
621
660
  };
622
661
  }
623
662
  function childrenToSlots(children, originalSlots) {