@nocobase/flow-engine 2.0.0-beta.8 → 2.0.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.
- package/lib/BlockScopedFlowEngine.js +0 -1
- package/lib/FlowDefinition.d.ts +2 -0
- package/lib/JSRunner.d.ts +6 -0
- package/lib/JSRunner.js +32 -2
- package/lib/ViewScopedFlowEngine.js +3 -0
- package/lib/acl/Acl.js +13 -3
- package/lib/components/FlowContextSelector.js +155 -10
- package/lib/components/settings/wrappers/component/SwitchWithTitle.js +2 -1
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +76 -15
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +24 -4
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +5 -1
- package/lib/components/variables/VariableInput.js +9 -4
- package/lib/components/variables/VariableTag.js +46 -39
- package/lib/components/variables/utils.d.ts +7 -0
- package/lib/components/variables/utils.js +42 -2
- package/lib/data-source/index.d.ts +7 -27
- package/lib/data-source/index.js +81 -51
- package/lib/executor/FlowExecutor.d.ts +2 -1
- package/lib/executor/FlowExecutor.js +163 -22
- package/lib/flowContext.d.ts +230 -7
- package/lib/flowContext.js +2267 -148
- package/lib/flowEngine.d.ts +21 -0
- package/lib/flowEngine.js +56 -8
- package/lib/flowI18n.js +6 -4
- package/lib/flowSettings.js +17 -11
- package/lib/index.d.ts +7 -1
- package/lib/index.js +21 -0
- package/lib/locale/en-US.json +9 -2
- package/lib/locale/index.d.ts +14 -0
- package/lib/locale/zh-CN.json +8 -1
- package/lib/models/CollectionFieldModel.d.ts +1 -0
- package/lib/models/CollectionFieldModel.js +3 -2
- package/lib/models/flowModel.js +12 -1
- package/lib/provider.js +5 -5
- package/lib/resources/baseRecordResource.d.ts +5 -0
- package/lib/resources/baseRecordResource.js +24 -0
- package/lib/resources/multiRecordResource.d.ts +1 -0
- package/lib/resources/multiRecordResource.js +11 -4
- package/lib/resources/singleRecordResource.js +2 -0
- package/lib/resources/sqlResource.d.ts +4 -3
- package/lib/resources/sqlResource.js +8 -3
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +12 -2
- package/lib/runjs-context/contexts/JSBlockRunJSContext.js +2 -2
- package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.js +125 -0
- package/lib/runjs-context/contexts/JSItemRunJSContext.js +12 -2
- package/lib/runjs-context/contexts/base.js +706 -41
- package/lib/runjs-context/contributions.d.ts +33 -0
- package/lib/runjs-context/contributions.js +88 -0
- package/lib/runjs-context/helpers.js +12 -1
- package/lib/runjs-context/setup.js +6 -0
- package/lib/runjs-context/snippets/global/api-request.snippet.js +3 -3
- package/lib/runjs-context/snippets/global/import-esm.snippet.js +2 -3
- package/lib/runjs-context/snippets/global/query-selector.snippet.js +8 -3
- package/lib/runjs-context/snippets/global/require-amd.snippet.js +1 -1
- package/lib/runjs-context/snippets/index.d.ts +11 -1
- package/lib/runjs-context/snippets/index.js +61 -40
- package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.js +10 -7
- package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +3 -3
- package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +2 -2
- package/lib/runjs-context/snippets/scene/block/echarts-init.snippet.js +2 -2
- package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +2 -2
- package/lib/runjs-context/snippets/scene/block/render-react.snippet.js +1 -1
- package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +1 -1
- package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +1 -1
- package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +5 -5
- package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +6 -6
- package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +3 -4
- package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.js +1 -1
- package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.js +20 -3
- package/lib/runjs-context/snippets/scene/detail/format-number.snippet.js +1 -1
- package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.js +1 -1
- package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +3 -3
- package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +3 -3
- package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +2 -2
- package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +1 -1
- package/lib/runjs-context/snippets/scene/form/render-basic.snippet.js +2 -2
- package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +6 -3
- package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +3 -1
- package/lib/runjsLibs.d.ts +28 -0
- package/lib/runjsLibs.js +532 -0
- package/lib/scheduler/ModelOperationScheduler.d.ts +2 -0
- package/lib/scheduler/ModelOperationScheduler.js +25 -21
- package/lib/types.d.ts +27 -0
- package/lib/utils/associationObjectVariable.d.ts +2 -2
- package/lib/utils/createCollectionContextMeta.js +1 -0
- package/lib/utils/createEphemeralContext.js +2 -2
- package/lib/utils/dateVariable.d.ts +16 -0
- package/lib/utils/dateVariable.js +380 -0
- package/lib/utils/exceptions.d.ts +7 -0
- package/lib/utils/exceptions.js +10 -0
- package/lib/utils/index.d.ts +8 -3
- package/lib/utils/index.js +45 -0
- package/lib/utils/params-resolvers.js +16 -9
- package/lib/utils/resolveModuleUrl.d.ts +58 -0
- package/lib/utils/resolveModuleUrl.js +65 -0
- package/lib/utils/resolveRunJSObjectValues.d.ts +16 -0
- package/lib/utils/resolveRunJSObjectValues.js +61 -0
- package/lib/utils/runjsModuleLoader.d.ts +58 -0
- package/lib/utils/runjsModuleLoader.js +422 -0
- package/lib/utils/runjsTemplateCompat.d.ts +35 -0
- package/lib/utils/runjsTemplateCompat.js +743 -0
- package/lib/utils/runjsValue.d.ts +29 -0
- package/lib/utils/runjsValue.js +275 -0
- package/lib/utils/safeGlobals.d.ts +18 -8
- package/lib/utils/safeGlobals.js +164 -17
- package/lib/utils/schema-utils.d.ts +10 -0
- package/lib/utils/schema-utils.js +61 -0
- package/lib/views/createViewMeta.d.ts +0 -7
- package/lib/views/createViewMeta.js +19 -70
- package/lib/views/index.d.ts +1 -2
- package/lib/views/index.js +4 -3
- package/lib/views/useDialog.js +7 -2
- package/lib/views/useDrawer.js +7 -2
- package/lib/views/usePage.d.ts +4 -0
- package/lib/views/usePage.js +43 -6
- package/lib/views/usePopover.js +4 -1
- package/lib/views/viewEvents.d.ts +17 -0
- package/lib/views/viewEvents.js +90 -0
- package/package.json +4 -4
- package/src/BlockScopedFlowEngine.ts +2 -5
- package/src/JSRunner.ts +44 -2
- package/src/ViewScopedFlowEngine.ts +4 -0
- package/src/__tests__/JSRunner.test.ts +64 -0
- package/src/__tests__/createViewMeta.popup.test.ts +62 -1
- package/src/__tests__/flowContext.test.ts +693 -1
- package/src/__tests__/flowEngine.dataSourceDirty.test.ts +63 -0
- package/src/__tests__/flowModel.openView.navigation.test.ts +28 -0
- package/src/__tests__/flowRunJSContextDefine.test.ts +63 -0
- package/src/__tests__/flowRuntimeContext.test.ts +2 -1
- package/src/__tests__/flowSettings.open.test.tsx +123 -19
- package/src/__tests__/runjsContext.test.ts +10 -7
- package/src/__tests__/runjsContextImplementations.test.ts +34 -3
- package/src/__tests__/runjsContextRuntime.test.ts +3 -3
- package/src/__tests__/runjsContributions.test.ts +89 -0
- package/src/__tests__/runjsExternalLibs.test.ts +242 -0
- package/src/__tests__/runjsLibsLazyLoading.test.ts +44 -0
- package/src/__tests__/runjsLocales.test.ts +4 -1
- package/src/__tests__/runjsPreprocessDefault.test.ts +49 -0
- package/src/__tests__/runjsRuntimeFeatures.test.ts +166 -0
- package/src/__tests__/runjsSnippets.test.ts +40 -3
- package/src/acl/Acl.tsx +3 -3
- package/src/components/FlowContextSelector.tsx +208 -12
- package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +2 -1
- package/src/components/settings/wrappers/component/__tests__/InlineControls.test.tsx +74 -0
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +109 -16
- package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +41 -7
- package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +13 -2
- package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +157 -5
- package/src/components/variables/VariableInput.tsx +12 -4
- package/src/components/variables/VariableTag.tsx +54 -45
- package/src/components/variables/__tests__/FlowContextSelector.test.tsx +260 -3
- package/src/components/variables/__tests__/VariableTag.test.tsx +50 -0
- package/src/components/variables/__tests__/utils.test.ts +81 -3
- package/src/components/variables/utils.ts +67 -6
- package/src/data-source/index.ts +85 -110
- package/src/executor/FlowExecutor.ts +200 -23
- package/src/executor/__tests__/flowExecutor.test.ts +66 -0
- package/src/flowContext.ts +2986 -211
- package/src/flowEngine.ts +59 -8
- package/src/flowI18n.ts +7 -5
- package/src/flowSettings.ts +18 -12
- package/src/index.ts +14 -1
- package/src/locale/en-US.json +9 -2
- package/src/locale/zh-CN.json +8 -1
- package/src/models/CollectionFieldModel.tsx +3 -1
- package/src/models/__tests__/dispatchEvent.when.test.ts +554 -0
- package/src/models/__tests__/flowModel.test.ts +20 -4
- package/src/models/flowModel.tsx +13 -1
- package/src/provider.tsx +7 -6
- package/src/resources/__tests__/multiRecordResource.test.ts +44 -0
- package/src/resources/__tests__/sqlResource.test.ts +60 -0
- package/src/resources/baseRecordResource.ts +31 -0
- package/src/resources/multiRecordResource.ts +11 -4
- package/src/resources/singleRecordResource.ts +3 -0
- package/src/resources/sqlResource.ts +11 -6
- package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +10 -0
- package/src/runjs-context/contexts/JSBlockRunJSContext.ts +6 -2
- package/src/runjs-context/contexts/JSEditableFieldRunJSContext.ts +106 -0
- package/src/runjs-context/contexts/JSItemRunJSContext.ts +10 -0
- package/src/runjs-context/contexts/base.ts +715 -44
- package/src/runjs-context/contributions.ts +88 -0
- package/src/runjs-context/helpers.ts +11 -1
- package/src/runjs-context/setup.ts +6 -0
- package/src/runjs-context/snippets/global/api-request.snippet.ts +3 -3
- package/src/runjs-context/snippets/global/import-esm.snippet.ts +2 -3
- package/src/runjs-context/snippets/global/query-selector.snippet.ts +8 -3
- package/src/runjs-context/snippets/global/require-amd.snippet.ts +1 -1
- package/src/runjs-context/snippets/index.ts +75 -41
- package/src/runjs-context/snippets/scene/block/add-event-listener.snippet.ts +11 -13
- package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +3 -3
- package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +2 -2
- package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +2 -2
- package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +2 -2
- package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +1 -1
- package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +1 -1
- package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +1 -1
- package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +6 -11
- package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +6 -6
- package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +3 -4
- package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +1 -1
- package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +20 -3
- package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +1 -1
- package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +1 -1
- package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +3 -3
- package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +3 -3
- package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +2 -2
- package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +1 -1
- package/src/runjs-context/snippets/scene/form/render-basic.snippet.ts +3 -8
- package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +6 -3
- package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +3 -1
- package/src/runjsLibs.ts +622 -0
- package/src/scheduler/ModelOperationScheduler.ts +27 -21
- package/src/types.ts +38 -1
- package/src/utils/__tests__/dateVariable.test.ts +101 -0
- package/src/utils/__tests__/params-resolvers.test.ts +40 -0
- package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +38 -0
- package/src/utils/__tests__/runjsTemplateCompat.test.ts +159 -0
- package/src/utils/__tests__/runjsValue.test.ts +44 -0
- package/src/utils/__tests__/safeGlobals.test.ts +57 -2
- package/src/utils/__tests__/utils.test.ts +95 -0
- package/src/utils/associationObjectVariable.ts +2 -2
- package/src/utils/createCollectionContextMeta.ts +1 -0
- package/src/utils/createEphemeralContext.ts +5 -4
- package/src/utils/dateVariable.ts +397 -0
- package/src/utils/exceptions.ts +11 -0
- package/src/utils/index.ts +37 -3
- package/src/utils/params-resolvers.ts +23 -9
- package/src/utils/resolveModuleUrl.ts +91 -0
- package/src/utils/resolveRunJSObjectValues.ts +46 -0
- package/src/utils/runjsModuleLoader.ts +553 -0
- package/src/utils/runjsTemplateCompat.ts +828 -0
- package/src/utils/runjsValue.ts +287 -0
- package/src/utils/safeGlobals.ts +188 -17
- package/src/utils/schema-utils.ts +79 -0
- package/src/views/__tests__/FlowView.usePage.test.tsx +54 -1
- package/src/views/__tests__/useDialog.closeDestroy.test.tsx +35 -8
- package/src/views/__tests__/viewEvents.resolveOpenerEngine.test.ts +28 -0
- package/src/views/createViewMeta.ts +22 -75
- package/src/views/index.tsx +1 -2
- package/src/views/useDialog.tsx +8 -1
- package/src/views/useDrawer.tsx +8 -1
- package/src/views/usePage.tsx +51 -5
- package/src/views/usePopover.tsx +4 -1
- package/src/views/viewEvents.ts +55 -0
package/src/runjsLibs.ts
ADDED
|
@@ -0,0 +1,622 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import * as antdIcons from '@ant-design/icons';
|
|
11
|
+
import { autorun } from '@formily/reactive';
|
|
12
|
+
import type { FlowContext } from './flowContext';
|
|
13
|
+
|
|
14
|
+
export type RunJSLibCache = 'global' | 'context';
|
|
15
|
+
export type RunJSLibLoader<T = any> = (ctx: FlowContext) => T | Promise<T>;
|
|
16
|
+
|
|
17
|
+
type RunJSLibRegistryEntry = {
|
|
18
|
+
loader: RunJSLibLoader<unknown>;
|
|
19
|
+
cache: RunJSLibCache;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const __runjsLibRegistry = new Map<string, RunJSLibRegistryEntry>();
|
|
23
|
+
|
|
24
|
+
const __runjsLibResolvedCache = new Map<string, unknown>();
|
|
25
|
+
const __runjsLibPendingCache = new Map<string, Promise<unknown>>();
|
|
26
|
+
const __runjsLibPendingByCtx = new WeakMap<FlowContext, Map<string, Promise<unknown>>>();
|
|
27
|
+
const __runjsErrorBoundaryByReact = new WeakMap<any, any>();
|
|
28
|
+
|
|
29
|
+
function __runjsGetPendingMapForCtx(ctx: FlowContext): Map<string, Promise<unknown>> {
|
|
30
|
+
let m = __runjsLibPendingByCtx.get(ctx);
|
|
31
|
+
if (!m) {
|
|
32
|
+
m = new Map<string, Promise<unknown>>();
|
|
33
|
+
__runjsLibPendingByCtx.set(ctx, m);
|
|
34
|
+
}
|
|
35
|
+
return m;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function registerRunJSLib(name: string, loader: RunJSLibLoader, options?: { cache?: RunJSLibCache }): void {
|
|
39
|
+
if (typeof name !== 'string' || !name) return;
|
|
40
|
+
if (typeof loader !== 'function') return;
|
|
41
|
+
__runjsLibRegistry.set(name, { loader, cache: options?.cache || 'global' });
|
|
42
|
+
// allow re-register to take effect on next ensure
|
|
43
|
+
__runjsLibResolvedCache.delete(name);
|
|
44
|
+
__runjsLibPendingCache.delete(name);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function __runjsIsObject(val: unknown): val is Record<string, unknown> {
|
|
48
|
+
return !!val && typeof val === 'object';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function __runjsHasOwn(obj: unknown, key: string): obj is Record<string, unknown> {
|
|
52
|
+
return __runjsIsObject(obj) && Object.prototype.hasOwnProperty.call(obj, key);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function __runjsIsPromiseLike(val: unknown): val is PromiseLike<unknown> {
|
|
56
|
+
if (!__runjsIsObject(val)) return false;
|
|
57
|
+
const then = (val as { then?: unknown }).then;
|
|
58
|
+
return typeof then === 'function';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function __runjsGetCtxValue(ctx: FlowContext, key: string): unknown {
|
|
62
|
+
return (ctx as unknown as Record<string, unknown>)[key];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function __runjsEnsureLib(ctx: FlowContext, name: string): Promise<unknown> {
|
|
66
|
+
const libs = (ctx as unknown as { libs?: unknown })?.libs;
|
|
67
|
+
if (__runjsHasOwn(libs, name)) {
|
|
68
|
+
const existing = libs[name];
|
|
69
|
+
if (typeof existing !== 'undefined') return existing;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const entry = __runjsLibRegistry.get(name);
|
|
73
|
+
if (!entry) return __runjsIsObject(libs) ? libs[name] : undefined;
|
|
74
|
+
|
|
75
|
+
const setLib = (v: unknown) => {
|
|
76
|
+
if (__runjsIsObject(libs)) libs[name] = v;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
if (entry.cache === 'context') {
|
|
80
|
+
const pendingMap = __runjsGetPendingMapForCtx(ctx);
|
|
81
|
+
const existingPending = pendingMap.get(name);
|
|
82
|
+
if (existingPending) {
|
|
83
|
+
const v = await existingPending;
|
|
84
|
+
setLib(v);
|
|
85
|
+
return v;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const task = Promise.resolve()
|
|
89
|
+
.then(() => entry.loader(ctx))
|
|
90
|
+
.then(
|
|
91
|
+
(v) => {
|
|
92
|
+
pendingMap.delete(name);
|
|
93
|
+
return v;
|
|
94
|
+
},
|
|
95
|
+
(err) => {
|
|
96
|
+
pendingMap.delete(name);
|
|
97
|
+
throw err;
|
|
98
|
+
},
|
|
99
|
+
);
|
|
100
|
+
pendingMap.set(name, task);
|
|
101
|
+
const v = await task;
|
|
102
|
+
setLib(v);
|
|
103
|
+
return v;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (__runjsLibResolvedCache.has(name)) {
|
|
107
|
+
const v = __runjsLibResolvedCache.get(name);
|
|
108
|
+
setLib(v);
|
|
109
|
+
return v;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const existingPending = __runjsLibPendingCache.get(name);
|
|
113
|
+
if (existingPending) {
|
|
114
|
+
const v = await existingPending;
|
|
115
|
+
setLib(v);
|
|
116
|
+
return v;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const task = Promise.resolve()
|
|
120
|
+
.then(() => entry.loader(ctx))
|
|
121
|
+
.then(
|
|
122
|
+
(v) => {
|
|
123
|
+
__runjsLibResolvedCache.set(name, v);
|
|
124
|
+
__runjsLibPendingCache.delete(name);
|
|
125
|
+
return v;
|
|
126
|
+
},
|
|
127
|
+
(err) => {
|
|
128
|
+
__runjsLibPendingCache.delete(name);
|
|
129
|
+
throw err;
|
|
130
|
+
},
|
|
131
|
+
);
|
|
132
|
+
__runjsLibPendingCache.set(name, task);
|
|
133
|
+
const v = await task;
|
|
134
|
+
setLib(v);
|
|
135
|
+
return v;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function setupRunJSLibAPIs(ctx: FlowContext): void {
|
|
139
|
+
if (!ctx || typeof ctx !== 'object') return;
|
|
140
|
+
if (typeof ctx.defineMethod !== 'function') return;
|
|
141
|
+
|
|
142
|
+
// Internal: ensure libs are loaded before first use.
|
|
143
|
+
// NOTE: name with `__` prefix to reduce accidental use; still callable from RunJS.
|
|
144
|
+
ctx.defineMethod('__ensureLib', async function (this: FlowContext, name: string) {
|
|
145
|
+
if (typeof name !== 'string' || !name) return undefined;
|
|
146
|
+
return await __runjsEnsureLib(this, name);
|
|
147
|
+
});
|
|
148
|
+
ctx.defineMethod('__ensureLibs', async function (this: FlowContext, names: unknown) {
|
|
149
|
+
if (!Array.isArray(names)) return;
|
|
150
|
+
for (const n of names) {
|
|
151
|
+
if (typeof n !== 'string' || !n) continue;
|
|
152
|
+
await __runjsEnsureLib(this, n);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const DEFAULT_RUNJS_LIBS: Array<{ name: string; cache: RunJSLibCache; loader: RunJSLibLoader }> = [
|
|
158
|
+
{ name: 'React', cache: 'context', loader: (ctx) => __runjsGetCtxValue(ctx, 'React') },
|
|
159
|
+
{ name: 'ReactDOM', cache: 'context', loader: (ctx) => __runjsGetCtxValue(ctx, 'ReactDOM') },
|
|
160
|
+
{ name: 'antd', cache: 'context', loader: (ctx) => __runjsGetCtxValue(ctx, 'antd') },
|
|
161
|
+
{ name: 'dayjs', cache: 'context', loader: (ctx) => __runjsGetCtxValue(ctx, 'dayjs') },
|
|
162
|
+
{ name: 'antdIcons', cache: 'global', loader: () => antdIcons },
|
|
163
|
+
{ name: 'lodash', cache: 'global', loader: () => import('lodash').then((m) => m.default || m) },
|
|
164
|
+
{ name: 'formula', cache: 'global', loader: () => import('@formulajs/formulajs').then((m) => m.default || m) },
|
|
165
|
+
{ name: 'math', cache: 'global', loader: () => import('mathjs').then((m) => m) },
|
|
166
|
+
];
|
|
167
|
+
|
|
168
|
+
let __defaultRunJSLibsRegistered = false;
|
|
169
|
+
|
|
170
|
+
function ensureDefaultRunJSLibsRegistered(): void {
|
|
171
|
+
if (__defaultRunJSLibsRegistered) return;
|
|
172
|
+
__defaultRunJSLibsRegistered = true;
|
|
173
|
+
for (const { name, loader, cache } of DEFAULT_RUNJS_LIBS) {
|
|
174
|
+
if (__runjsLibRegistry.has(name)) continue;
|
|
175
|
+
registerRunJSLib(name, loader, { cache });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function resolveRegisteredLibSync(ctx: FlowContext, name: string): unknown {
|
|
180
|
+
const entry = __runjsLibRegistry.get(name);
|
|
181
|
+
if (!entry) return undefined;
|
|
182
|
+
if (entry.cache === 'global' && __runjsLibResolvedCache.has(name)) {
|
|
183
|
+
return __runjsLibResolvedCache.get(name);
|
|
184
|
+
}
|
|
185
|
+
const v = entry.loader(ctx);
|
|
186
|
+
if (__runjsIsPromiseLike(v)) return undefined;
|
|
187
|
+
if (entry.cache === 'global') __runjsLibResolvedCache.set(name, v);
|
|
188
|
+
return v;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function setupRunJSLibs(ctx: FlowContext): void {
|
|
192
|
+
if (!ctx || typeof ctx !== 'object') return;
|
|
193
|
+
if (typeof ctx.defineProperty !== 'function') return;
|
|
194
|
+
|
|
195
|
+
ensureDefaultRunJSLibsRegistered();
|
|
196
|
+
|
|
197
|
+
// 为第三方/通用库提供统一命名空间:ctx.libs
|
|
198
|
+
// - 新增库应优先挂载到 ctx.libs.xxx(通过 registerRunJSLib)
|
|
199
|
+
// - 同时保留顶层别名(如 ctx.React / ctx.antd),以兼容历史代码
|
|
200
|
+
const libs: Record<string, unknown> = {};
|
|
201
|
+
for (const { name } of DEFAULT_RUNJS_LIBS) {
|
|
202
|
+
Object.defineProperty(libs, name, {
|
|
203
|
+
configurable: true,
|
|
204
|
+
enumerable: true,
|
|
205
|
+
get() {
|
|
206
|
+
const v = resolveRegisteredLibSync(ctx, name);
|
|
207
|
+
// Lazy materialize as writable data property on first access
|
|
208
|
+
Object.defineProperty(libs, name, {
|
|
209
|
+
configurable: true,
|
|
210
|
+
enumerable: true,
|
|
211
|
+
writable: true,
|
|
212
|
+
value: v,
|
|
213
|
+
});
|
|
214
|
+
return v;
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
ctx.defineProperty('libs', { value: libs });
|
|
219
|
+
setupRunJSLibAPIs(ctx);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function setRunJSLibOverride(
|
|
223
|
+
ctx: FlowContext,
|
|
224
|
+
name: string,
|
|
225
|
+
value: unknown,
|
|
226
|
+
options?: { topLevelKey?: string | false },
|
|
227
|
+
): void {
|
|
228
|
+
const topLevelKey = options?.topLevelKey === false ? null : options?.topLevelKey || name;
|
|
229
|
+
if (topLevelKey) {
|
|
230
|
+
ctx.defineProperty(topLevelKey, { value });
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const libs = ctx.libs;
|
|
234
|
+
Object.defineProperty(libs, name, {
|
|
235
|
+
configurable: true,
|
|
236
|
+
enumerable: true,
|
|
237
|
+
writable: true,
|
|
238
|
+
value,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function buildMixedReactHint(options: { ctx: any; internalReact: any; internalAntd: any }): string {
|
|
243
|
+
const { ctx, internalReact, internalAntd } = options;
|
|
244
|
+
|
|
245
|
+
const lines: string[] = [];
|
|
246
|
+
const externalReact = ctx.React && ctx.React !== internalReact;
|
|
247
|
+
const internalReactDOM = !!(ctx.ReactDOM as any)?.__nbRunjsInternalShim;
|
|
248
|
+
const usingInternalAntd = ctx.antd === internalAntd;
|
|
249
|
+
const externalAntd = ctx.antd && ctx.antd !== internalAntd;
|
|
250
|
+
|
|
251
|
+
if (externalReact && internalReactDOM) {
|
|
252
|
+
const reactInfo = ctx.__runjsExternalReact;
|
|
253
|
+
const v = reactInfo?.version;
|
|
254
|
+
const domHint = v ? `react-dom@${v}/client` : 'react-dom/client';
|
|
255
|
+
lines.push(
|
|
256
|
+
`- You have imported external React, but you're still using the built-in ReactDOM Root; please also run: await ctx.importAsync("${domHint}")`,
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
if (externalAntd && !externalReact) {
|
|
260
|
+
lines.push(
|
|
261
|
+
`- You have imported external antd, but you're still using the built-in React; please run: await ctx.importAsync("react@18.x")`,
|
|
262
|
+
);
|
|
263
|
+
lines.push(`- And make sure ReactDOM matches: await ctx.importAsync("react-dom@18.x/client")`);
|
|
264
|
+
}
|
|
265
|
+
if (externalReact && usingInternalAntd) {
|
|
266
|
+
lines.push(
|
|
267
|
+
`- You have imported external React, but you're still using the built-in antd; please switch to: await ctx.importAsync("antd@5.x")`,
|
|
268
|
+
);
|
|
269
|
+
lines.push(`- If you use icon components, also import: await ctx.importAsync("@ant-design/icons@5.x")`);
|
|
270
|
+
}
|
|
271
|
+
return lines.length ? `\n\n[RunJS Hint]\n${lines.join('\n')}` : '';
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function isReactHooksDispatcherNullError(err: any): boolean {
|
|
275
|
+
const msg = String(err?.message || '');
|
|
276
|
+
if (!msg) return false;
|
|
277
|
+
// React prod build may throw TypeError instead of a descriptive "Invalid hook call" message
|
|
278
|
+
// when the hook dispatcher is null (common when multiple React instances are loaded).
|
|
279
|
+
if (!/Cannot read (?:properties|property) of (?:null|undefined) \(reading 'use[A-Za-z]+'\)/.test(msg)) return false;
|
|
280
|
+
|
|
281
|
+
const stack = String(err?.stack || '');
|
|
282
|
+
if (!stack) return false;
|
|
283
|
+
// Common cases:
|
|
284
|
+
// - ESM CDN: https://esm.sh/react@x.y.z/.../react.mjs
|
|
285
|
+
// - other builds: react.development.js / react.production.min.js
|
|
286
|
+
return (
|
|
287
|
+
/(?:^|\W)react@[^/\s)]+/i.test(stack) ||
|
|
288
|
+
/react\.mjs/i.test(stack) ||
|
|
289
|
+
/react\.(?:development|production)/i.test(stack)
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function extractReactVersionFromStack(err: any): string | undefined {
|
|
294
|
+
const stack = String(err?.stack || '');
|
|
295
|
+
if (!stack) return undefined;
|
|
296
|
+
// Prefer explicit `react@x.y.z` segments from stack (esm.sh and similar CDNs).
|
|
297
|
+
const m = stack.match(/(?:^|\W)react@([^/\s)]+)/i);
|
|
298
|
+
const v = m?.[1]?.trim();
|
|
299
|
+
return v || undefined;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function buildReactDispatcherNullHint(options: { ctx: any; internalReact: any; internalAntd: any; err: any }): string {
|
|
303
|
+
const { ctx, internalReact, internalAntd, err } = options;
|
|
304
|
+
if (!isReactHooksDispatcherNullError(err)) return '';
|
|
305
|
+
|
|
306
|
+
const v = extractReactVersionFromStack(err);
|
|
307
|
+
const lines: string[] = [];
|
|
308
|
+
|
|
309
|
+
lines.push(`- This looks like a React Hooks crash caused by multiple React instances (hook dispatcher is null).`);
|
|
310
|
+
if (v) {
|
|
311
|
+
lines.push(`- Your stack trace includes external React: react@${v}.`);
|
|
312
|
+
lines.push(
|
|
313
|
+
`- Fix: import the same React BEFORE you read ctx.libs.React / call hooks / import React-based libs: await ctx.importAsync("react@${v}")`,
|
|
314
|
+
);
|
|
315
|
+
} else {
|
|
316
|
+
lines.push(
|
|
317
|
+
`- Fix: import external React BEFORE you read ctx.libs.React / call hooks / import React-based libs (use the same version shown in the stack trace).`,
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const usingInternalAntd = ctx.antd === internalAntd;
|
|
322
|
+
if (usingInternalAntd) {
|
|
323
|
+
lines.push(`- If you use antd components, also switch to external antd: await ctx.importAsync("antd@5.x")`);
|
|
324
|
+
lines.push(`- If you use icon components, also import: await ctx.importAsync("@ant-design/icons@5.x")`);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return lines.length ? `\n\n[RunJS Hint]\n${lines.join('\n')}` : '';
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function wrapErrorWithHint(err: any, messageWithHint: string): any {
|
|
331
|
+
const e: any = new Error(messageWithHint);
|
|
332
|
+
e.cause = err;
|
|
333
|
+
|
|
334
|
+
// Best-effort: preserve the original error "name" (e.g. TypeError) and stack frames for debugging.
|
|
335
|
+
try {
|
|
336
|
+
const name = typeof err?.name === 'string' ? err.name : '';
|
|
337
|
+
if (name) e.name = name;
|
|
338
|
+
} catch (_) {
|
|
339
|
+
// ignore
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
const stack = typeof err?.stack === 'string' ? err.stack : '';
|
|
343
|
+
if (stack) {
|
|
344
|
+
const lines = String(stack).split('\n');
|
|
345
|
+
if (lines.length) {
|
|
346
|
+
lines[0] = `${e.name}: ${messageWithHint}`;
|
|
347
|
+
e.stack = lines.join('\n');
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
} catch (_) {
|
|
351
|
+
// ignore
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return e;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function getRunjsErrorBoundary(ReactLike: any): any {
|
|
358
|
+
if (!ReactLike) return null;
|
|
359
|
+
const cached = __runjsErrorBoundaryByReact.get(ReactLike);
|
|
360
|
+
if (cached) return cached;
|
|
361
|
+
if (typeof ReactLike.createElement !== 'function') return null;
|
|
362
|
+
const Base = ReactLike.Component;
|
|
363
|
+
if (typeof Base !== 'function') return null;
|
|
364
|
+
|
|
365
|
+
class RunjsErrorBoundary extends Base {
|
|
366
|
+
static getDerivedStateFromError(error: any) {
|
|
367
|
+
return { error };
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
state: { error?: any } = {};
|
|
371
|
+
|
|
372
|
+
componentDidCatch(error: any) {
|
|
373
|
+
try {
|
|
374
|
+
const enhance = (this.props as any)?.enhanceReactError;
|
|
375
|
+
const enhanced = typeof enhance === 'function' ? enhance(error) : error;
|
|
376
|
+
const msg = String(enhanced?.message || '');
|
|
377
|
+
if (msg && /\[RunJS Hint\]/.test(msg)) {
|
|
378
|
+
// React 18/19 often logs the original error (or swallows it from caller of root.render).
|
|
379
|
+
// Emit an extra, more actionable message for RunJS users.
|
|
380
|
+
console.error(msg);
|
|
381
|
+
const logger = (this.props as any)?.ctx?.logger;
|
|
382
|
+
if (logger && typeof logger.error === 'function') {
|
|
383
|
+
logger.error(msg);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
} catch (_) {
|
|
387
|
+
// ignore
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
componentDidUpdate(prevProps: any) {
|
|
392
|
+
// Allow recovery on subsequent ctx.render calls
|
|
393
|
+
if (prevProps?.resetKey !== (this.props as any)?.resetKey && this.state?.error) {
|
|
394
|
+
this.setState({ error: undefined });
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
render() {
|
|
399
|
+
const error = this.state?.error;
|
|
400
|
+
if (!error) return (this.props as any).children;
|
|
401
|
+
|
|
402
|
+
let msg = '';
|
|
403
|
+
try {
|
|
404
|
+
const enhance = (this.props as any)?.enhanceReactError;
|
|
405
|
+
const enhanced = typeof enhance === 'function' ? enhance(error) : error;
|
|
406
|
+
msg = String(enhanced?.message || enhanced || error?.message || error || '');
|
|
407
|
+
} catch (_) {
|
|
408
|
+
msg = String(error?.message || error || '');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const containerStyle: any = {
|
|
412
|
+
boxSizing: 'border-box',
|
|
413
|
+
padding: 12,
|
|
414
|
+
borderRadius: 6,
|
|
415
|
+
border: '1px solid #ffccc7',
|
|
416
|
+
background: '#fff2f0',
|
|
417
|
+
color: '#a8071a',
|
|
418
|
+
fontSize: 12,
|
|
419
|
+
lineHeight: 1.5,
|
|
420
|
+
maxWidth: '100%',
|
|
421
|
+
overflow: 'auto',
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
const preStyle: any = {
|
|
425
|
+
margin: 0,
|
|
426
|
+
whiteSpace: 'pre-wrap',
|
|
427
|
+
wordBreak: 'break-word',
|
|
428
|
+
fontFamily:
|
|
429
|
+
'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
const titleStyle: any = { fontWeight: 600, marginBottom: 8 };
|
|
433
|
+
|
|
434
|
+
return ReactLike.createElement(
|
|
435
|
+
'div',
|
|
436
|
+
{ style: containerStyle },
|
|
437
|
+
ReactLike.createElement('div', { style: titleStyle }, 'RunJS render error'),
|
|
438
|
+
ReactLike.createElement('pre', { style: preStyle }, msg),
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
__runjsErrorBoundaryByReact.set(ReactLike, RunjsErrorBoundary);
|
|
444
|
+
return RunjsErrorBoundary;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function wrapVnodeWithRunjsErrorBoundary(options: {
|
|
448
|
+
ctx: any;
|
|
449
|
+
vnode: any;
|
|
450
|
+
enhanceReactError: (err: any) => any;
|
|
451
|
+
resetKey: number;
|
|
452
|
+
}): any {
|
|
453
|
+
const { ctx, vnode, enhanceReactError, resetKey } = options;
|
|
454
|
+
const ReactLike = ctx?.React;
|
|
455
|
+
const Boundary = getRunjsErrorBoundary(ReactLike);
|
|
456
|
+
if (!Boundary) return vnode;
|
|
457
|
+
return ReactLike.createElement(Boundary, { ctx, enhanceReactError, resetKey }, vnode);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function tryRenderWithExternalAntdTheme(options: {
|
|
461
|
+
ctx: any;
|
|
462
|
+
entry: any;
|
|
463
|
+
containerEl: any;
|
|
464
|
+
rootMap: WeakMap<any, any>;
|
|
465
|
+
unmountContainerRoot: () => void;
|
|
466
|
+
enhanceReactError: (err: any) => any;
|
|
467
|
+
internalReact: any;
|
|
468
|
+
internalAntd: any;
|
|
469
|
+
}): boolean {
|
|
470
|
+
const { ctx, entry, containerEl, rootMap, unmountContainerRoot, enhanceReactError, internalReact, internalAntd } =
|
|
471
|
+
options;
|
|
472
|
+
|
|
473
|
+
const canUseExternalAntd =
|
|
474
|
+
!(ctx.ReactDOM as any)?.__nbRunjsInternalShim &&
|
|
475
|
+
ctx.React &&
|
|
476
|
+
ctx.React !== internalReact &&
|
|
477
|
+
ctx.antd &&
|
|
478
|
+
ctx.antd !== internalAntd &&
|
|
479
|
+
typeof (ctx.antd as any).ConfigProvider !== 'undefined';
|
|
480
|
+
|
|
481
|
+
if (!canUseExternalAntd) {
|
|
482
|
+
if (entry.disposeTheme) {
|
|
483
|
+
try {
|
|
484
|
+
entry.disposeTheme();
|
|
485
|
+
} catch (_) {
|
|
486
|
+
// ignore
|
|
487
|
+
}
|
|
488
|
+
entry.disposeTheme = undefined;
|
|
489
|
+
}
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const renderWithExternalAntdTheme = () => {
|
|
494
|
+
// Make theme token reactive dependency (best-effort)
|
|
495
|
+
const themeToken = ctx?.engine?.context?.themeToken;
|
|
496
|
+
void themeToken;
|
|
497
|
+
|
|
498
|
+
const appConfig = ctx?.engine?.context?.antdConfig;
|
|
499
|
+
const locale = ctx?.engine?.context?.locales?.antd || appConfig?.locale;
|
|
500
|
+
|
|
501
|
+
const ConfigProvider = (ctx.antd as any).ConfigProvider;
|
|
502
|
+
const App = (ctx.antd as any).App;
|
|
503
|
+
|
|
504
|
+
const configProps: any = {
|
|
505
|
+
popupMatchSelectWidth: false,
|
|
506
|
+
locale: locale || {},
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
if (appConfig && typeof appConfig === 'object') {
|
|
510
|
+
if (typeof appConfig.direction !== 'undefined') configProps.direction = appConfig.direction;
|
|
511
|
+
if (typeof appConfig.prefixCls === 'string') configProps.prefixCls = appConfig.prefixCls;
|
|
512
|
+
if (typeof appConfig.iconPrefixCls === 'string') configProps.iconPrefixCls = appConfig.iconPrefixCls;
|
|
513
|
+
if (typeof appConfig.getPopupContainer === 'function')
|
|
514
|
+
configProps.getPopupContainer = appConfig.getPopupContainer;
|
|
515
|
+
if (appConfig.theme && typeof appConfig.theme === 'object') configProps.theme = appConfig.theme;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const child = entry.lastVnode as any;
|
|
519
|
+
const wrapped = App
|
|
520
|
+
? ctx.React.createElement(ConfigProvider, configProps, ctx.React.createElement(App, null, child))
|
|
521
|
+
: ctx.React.createElement(ConfigProvider, configProps, child);
|
|
522
|
+
|
|
523
|
+
entry.root.render(wrapped);
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
if (!entry.disposeTheme) {
|
|
527
|
+
entry.disposeTheme = autorun(() => {
|
|
528
|
+
try {
|
|
529
|
+
// 兜底:如果容器节点曾经连接过 DOM,但后续又被移除(且仍被外部引用),
|
|
530
|
+
// autorun 继续运行会导致泄漏;因此这里在“连接→断开”后执行清理。
|
|
531
|
+
//
|
|
532
|
+
// 注意:不在首次 render 就用 isConnected 拦截:
|
|
533
|
+
// - React 允许渲染到“未挂载到 DOM 的容器”(如离屏渲染/测试);
|
|
534
|
+
// - 因此只在容器“曾连接过”之后再做断开检测。
|
|
535
|
+
// 同时 DocumentFragment 的 isConnected 通常为 false,因此这里只对 Element 做判断。
|
|
536
|
+
if (
|
|
537
|
+
containerEl &&
|
|
538
|
+
containerEl.nodeType === 1 &&
|
|
539
|
+
typeof (containerEl as any).isConnected === 'boolean' &&
|
|
540
|
+
!(containerEl as any).isConnected &&
|
|
541
|
+
entry.wasConnected
|
|
542
|
+
) {
|
|
543
|
+
queueMicrotask(() => {
|
|
544
|
+
const cur = rootMap.get(containerEl);
|
|
545
|
+
if (cur === entry) unmountContainerRoot();
|
|
546
|
+
});
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
if (
|
|
550
|
+
containerEl &&
|
|
551
|
+
containerEl.nodeType === 1 &&
|
|
552
|
+
typeof (containerEl as any).isConnected === 'boolean' &&
|
|
553
|
+
(containerEl as any).isConnected
|
|
554
|
+
) {
|
|
555
|
+
entry.wasConnected = true;
|
|
556
|
+
}
|
|
557
|
+
renderWithExternalAntdTheme();
|
|
558
|
+
} catch (e) {
|
|
559
|
+
throw enhanceReactError(e);
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
} else {
|
|
563
|
+
renderWithExternalAntdTheme();
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return true;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
export function externalReactRender(options: {
|
|
570
|
+
ctx: any;
|
|
571
|
+
entry: any;
|
|
572
|
+
vnode: any;
|
|
573
|
+
containerEl: any;
|
|
574
|
+
rootMap: WeakMap<any, any>;
|
|
575
|
+
unmountContainerRoot: () => void;
|
|
576
|
+
internalReact: any;
|
|
577
|
+
internalAntd: any;
|
|
578
|
+
}): any {
|
|
579
|
+
const { ctx, entry, vnode, containerEl, rootMap, unmountContainerRoot, internalReact, internalAntd } = options;
|
|
580
|
+
|
|
581
|
+
const enhanceReactError = (err: any) => {
|
|
582
|
+
const msg = String(err?.message || err || '');
|
|
583
|
+
if (!msg) return err;
|
|
584
|
+
if (/\[RunJS Hint\]/.test(msg)) return err;
|
|
585
|
+
|
|
586
|
+
const invalidHookCall = /invalid hook call/i.test(msg);
|
|
587
|
+
const dispatcherNull = isReactHooksDispatcherNullError(err);
|
|
588
|
+
if (!invalidHookCall && !dispatcherNull) return err;
|
|
589
|
+
|
|
590
|
+
const hint =
|
|
591
|
+
buildMixedReactHint({ ctx, internalReact, internalAntd }) ||
|
|
592
|
+
buildReactDispatcherNullHint({ ctx, internalReact, internalAntd, err });
|
|
593
|
+
if (!hint) return err;
|
|
594
|
+
return wrapErrorWithHint(err, `${msg}${hint}`);
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
try {
|
|
598
|
+
entry.__nbRunjsRenderSeq = (entry.__nbRunjsRenderSeq || 0) + 1;
|
|
599
|
+
entry.lastVnode = wrapVnodeWithRunjsErrorBoundary({
|
|
600
|
+
ctx,
|
|
601
|
+
vnode,
|
|
602
|
+
enhanceReactError,
|
|
603
|
+
resetKey: entry.__nbRunjsRenderSeq,
|
|
604
|
+
});
|
|
605
|
+
const renderedWithExternalAntdTheme = tryRenderWithExternalAntdTheme({
|
|
606
|
+
ctx,
|
|
607
|
+
entry,
|
|
608
|
+
containerEl,
|
|
609
|
+
rootMap,
|
|
610
|
+
unmountContainerRoot,
|
|
611
|
+
enhanceReactError,
|
|
612
|
+
internalReact,
|
|
613
|
+
internalAntd,
|
|
614
|
+
});
|
|
615
|
+
if (!renderedWithExternalAntdTheme) {
|
|
616
|
+
entry.root.render(entry.lastVnode as any);
|
|
617
|
+
}
|
|
618
|
+
return entry.root;
|
|
619
|
+
} catch (e) {
|
|
620
|
+
throw enhanceReactError(e);
|
|
621
|
+
}
|
|
622
|
+
}
|