@nocobase/flow-engine 2.2.0-beta.5 → 2.2.0-beta.7

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 (30) hide show
  1. package/lib/JSRunner.d.ts +1 -0
  2. package/lib/JSRunner.js +110 -20
  3. package/lib/components/dnd/index.js +9 -2
  4. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +86 -32
  5. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.js +20 -0
  6. package/lib/flowContext.js +65 -30
  7. package/lib/runjs-context/helpers.js +12 -5
  8. package/lib/utils/index.d.ts +0 -1
  9. package/lib/utils/index.js +0 -11
  10. package/lib/utils/resolveRunJSObjectValues.js +3 -2
  11. package/lib/utils/runjsModuleLoader.js +0 -30
  12. package/package.json +4 -4
  13. package/src/JSRunner.ts +112 -25
  14. package/src/__tests__/JSRunner.test.ts +4 -5
  15. package/src/__tests__/flowContext.test.ts +43 -0
  16. package/src/__tests__/flowModel.openView.navigation.test.ts +28 -0
  17. package/src/components/dnd/index.tsx +11 -2
  18. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +105 -35
  19. package/src/components/settings/wrappers/contextual/__tests__/FlowsFloatContextMenu.test.tsx +381 -12
  20. package/src/components/settings/wrappers/contextual/useFloatToolbarVisibility.ts +28 -0
  21. package/src/flowContext.ts +68 -26
  22. package/src/runjs-context/helpers.ts +12 -6
  23. package/src/utils/index.ts +0 -9
  24. package/src/utils/resolveRunJSObjectValues.ts +5 -2
  25. package/src/utils/runjsModuleLoader.ts +0 -32
  26. package/lib/utils/safeGlobals.d.ts +0 -28
  27. package/lib/utils/safeGlobals.js +0 -367
  28. package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +0 -38
  29. package/src/utils/__tests__/safeGlobals.test.ts +0 -106
  30. package/src/utils/safeGlobals.ts +0 -406
package/lib/JSRunner.d.ts CHANGED
@@ -27,6 +27,7 @@ export interface JSRunnerOptions {
27
27
  * 3. Fallback keeps v1-compatible behavior (enabled).
28
28
  */
29
29
  export declare function shouldPreprocessRunJSTemplates(options?: Pick<JSRunnerOptions, 'preprocessTemplates' | 'version'>): boolean;
30
+ export declare const RUNJS_ALLOWED_BARE_GLOBAL_NAMES: readonly ["ctx", "console", "window", "document", "navigator", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "Array", "ArrayBuffer", "BigInt", "BigInt64Array", "BigUint64Array", "Boolean", "DataView", "Date", "Error", "EvalError", "FinalizationRegistry", "Float32Array", "Float64Array", "Int8Array", "Int16Array", "Int32Array", "Map", "Math", "Number", "Object", "Promise", "Proxy", "RangeError", "ReferenceError", "Reflect", "RegExp", "Set", "String", "Symbol", "SyntaxError", "TypeError", "URIError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap", "WeakRef", "WeakSet", "JSON", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "isFinite", "isNaN", "parseFloat", "parseInt", "undefined", "NaN", "Infinity", "fetch", "localStorage", "sessionStorage", "XMLHttpRequest", "WebSocket", "Worker", "SharedWorker", "ServiceWorker", "BroadcastChannel", "EventSource", "indexedDB", "caches", "Function", "eval", "globalThis", "Intl", "Blob", "URL", "location"];
30
31
  export declare class JSRunner {
31
32
  private globals;
32
33
  private timeoutMs;
package/lib/JSRunner.js CHANGED
@@ -28,6 +28,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
28
28
  var JSRunner_exports = {};
29
29
  __export(JSRunner_exports, {
30
30
  JSRunner: () => JSRunner,
31
+ RUNJS_ALLOWED_BARE_GLOBAL_NAMES: () => RUNJS_ALLOWED_BARE_GLOBAL_NAMES,
31
32
  shouldPreprocessRunJSTemplates: () => shouldPreprocessRunJSTemplates
32
33
  });
33
34
  module.exports = __toCommonJS(JSRunner_exports);
@@ -40,6 +41,113 @@ function shouldPreprocessRunJSTemplates(options) {
40
41
  return (options == null ? void 0 : options.version) !== "v2";
41
42
  }
42
43
  __name(shouldPreprocessRunJSTemplates, "shouldPreprocessRunJSTemplates");
44
+ const RUNJS_BROWSER_GLOBAL_NAMES = [
45
+ "fetch",
46
+ "localStorage",
47
+ "sessionStorage",
48
+ "XMLHttpRequest",
49
+ "WebSocket",
50
+ "Worker",
51
+ "SharedWorker",
52
+ "ServiceWorker",
53
+ "BroadcastChannel",
54
+ "EventSource",
55
+ "indexedDB",
56
+ "caches",
57
+ "Function",
58
+ "eval",
59
+ "globalThis",
60
+ "Intl",
61
+ "Blob",
62
+ "URL",
63
+ "location"
64
+ ];
65
+ const RUNJS_ALLOWED_BARE_GLOBAL_NAMES = [
66
+ "ctx",
67
+ "console",
68
+ "window",
69
+ "document",
70
+ "navigator",
71
+ "setTimeout",
72
+ "clearTimeout",
73
+ "setInterval",
74
+ "clearInterval",
75
+ "Array",
76
+ "ArrayBuffer",
77
+ "BigInt",
78
+ "BigInt64Array",
79
+ "BigUint64Array",
80
+ "Boolean",
81
+ "DataView",
82
+ "Date",
83
+ "Error",
84
+ "EvalError",
85
+ "FinalizationRegistry",
86
+ "Float32Array",
87
+ "Float64Array",
88
+ "Int8Array",
89
+ "Int16Array",
90
+ "Int32Array",
91
+ "Map",
92
+ "Math",
93
+ "Number",
94
+ "Object",
95
+ "Promise",
96
+ "Proxy",
97
+ "RangeError",
98
+ "ReferenceError",
99
+ "Reflect",
100
+ "RegExp",
101
+ "Set",
102
+ "String",
103
+ "Symbol",
104
+ "SyntaxError",
105
+ "TypeError",
106
+ "URIError",
107
+ "Uint8Array",
108
+ "Uint8ClampedArray",
109
+ "Uint16Array",
110
+ "Uint32Array",
111
+ "WeakMap",
112
+ "WeakRef",
113
+ "WeakSet",
114
+ "JSON",
115
+ "decodeURI",
116
+ "decodeURIComponent",
117
+ "encodeURI",
118
+ "encodeURIComponent",
119
+ "isFinite",
120
+ "isNaN",
121
+ "parseFloat",
122
+ "parseInt",
123
+ "undefined",
124
+ "NaN",
125
+ "Infinity",
126
+ ...RUNJS_BROWSER_GLOBAL_NAMES
127
+ ];
128
+ function collectRunJSBrowserGlobals(providedGlobals = {}) {
129
+ const windowGlobal = providedGlobals.window;
130
+ if (!windowGlobal || typeof windowGlobal !== "object") {
131
+ return {};
132
+ }
133
+ const windowRecord = windowGlobal;
134
+ const globals = {};
135
+ RUNJS_BROWSER_GLOBAL_NAMES.forEach((name) => {
136
+ if (Object.prototype.hasOwnProperty.call(providedGlobals, name)) {
137
+ return;
138
+ }
139
+ try {
140
+ const value = windowRecord[name];
141
+ if (typeof value === "undefined") {
142
+ return;
143
+ }
144
+ globals[name] = name === "fetch" && typeof value === "function" ? value.bind(windowGlobal) : value;
145
+ } catch {
146
+ }
147
+ });
148
+ return globals;
149
+ }
150
+ __name(collectRunJSBrowserGlobals, "collectRunJSBrowserGlobals");
43
151
  const BARE_CTX_TEMPLATE_RE = /(^|[=(:,[\s)])(\{\{\s*(ctx(?:\.|\[|\?\.)[^}]*)\s*\}\})/m;
44
152
  function extractDeprecatedCtxTemplateUsage(code) {
45
153
  const src = String(code || "");
@@ -78,7 +186,6 @@ const _JSRunner = class _JSRunner {
78
186
  globals;
79
187
  timeoutMs;
80
188
  constructor(options = {}) {
81
- var _a, _b;
82
189
  const bindWindowFn = /* @__PURE__ */ __name((key) => {
83
190
  if (typeof window !== "undefined" && typeof window[key] === "function") {
84
191
  return window[key].bind(window);
@@ -87,25 +194,7 @@ const _JSRunner = class _JSRunner {
87
194
  return typeof fn === "function" ? fn.bind(globalThis) : fn;
88
195
  }, "bindWindowFn");
89
196
  const providedGlobals = options.globals || {};
90
- const liftedGlobals = {};
91
- if (!Object.prototype.hasOwnProperty.call(providedGlobals, "Blob")) {
92
- try {
93
- const blobCtor = (_a = providedGlobals.window) == null ? void 0 : _a.Blob;
94
- if (typeof blobCtor !== "undefined") {
95
- liftedGlobals.Blob = blobCtor;
96
- }
97
- } catch {
98
- }
99
- }
100
- if (!Object.prototype.hasOwnProperty.call(providedGlobals, "URL")) {
101
- try {
102
- const urlCtor = (_b = providedGlobals.window) == null ? void 0 : _b.URL;
103
- if (typeof urlCtor !== "undefined") {
104
- liftedGlobals.URL = urlCtor;
105
- }
106
- } catch {
107
- }
108
- }
197
+ const liftedGlobals = collectRunJSBrowserGlobals(providedGlobals);
109
198
  this.globals = {
110
199
  console,
111
200
  setTimeout: bindWindowFn("setTimeout"),
@@ -169,5 +258,6 @@ let JSRunner = _JSRunner;
169
258
  // Annotate the CommonJS export names for ESM import in node:
170
259
  0 && (module.exports = {
171
260
  JSRunner,
261
+ RUNJS_ALLOWED_BARE_GLOBAL_NAMES,
172
262
  shouldPreprocessRunJSTemplates
173
263
  });
@@ -57,6 +57,10 @@ const EMPTY_COLUMN_UID = "EMPTY_COLUMN";
57
57
  const TOOLBAR_DRAG_ACTIVITY_EVENT = "nb-toolbar-drag-activity";
58
58
  const TOOLBAR_DRAG_ANCHOR_EVENT = "nb-toolbar-drag-anchor";
59
59
  const MENU_SUBMENU_POPUP_SELECTOR = ".ant-menu-submenu-popup";
60
+ const getToolbarModelUidFromNode = /* @__PURE__ */ __name((node) => {
61
+ var _a;
62
+ return ((_a = node == null ? void 0 : node.closest(".nb-toolbar-container[data-model-uid]")) == null ? void 0 : _a.getAttribute("data-model-uid")) || null;
63
+ }, "getToolbarModelUidFromNode");
60
64
  const resolveOverlayAnchorTransform = /* @__PURE__ */ __name(({
61
65
  activeId,
62
66
  active,
@@ -76,7 +80,7 @@ const resolveOverlayAnchorTransform = /* @__PURE__ */ __name(({
76
80
  const resolveDraggableHostNode = /* @__PURE__ */ __name((activatorNode) => {
77
81
  const ownerDocument = activatorNode == null ? void 0 : activatorNode.ownerDocument;
78
82
  const floatToolbarContainer = activatorNode == null ? void 0 : activatorNode.closest(".nb-toolbar-container[data-model-uid]");
79
- const toolbarModelUid = floatToolbarContainer == null ? void 0 : floatToolbarContainer.getAttribute("data-model-uid");
83
+ const toolbarModelUid = getToolbarModelUidFromNode(activatorNode);
80
84
  if (!ownerDocument || !toolbarModelUid) {
81
85
  return activatorNode;
82
86
  }
@@ -99,6 +103,7 @@ const DragHandler = /* @__PURE__ */ __name(({
99
103
  const dragHandlerRef = (0, import_react.useRef)(null);
100
104
  const draggableNodeRef = (0, import_react.useRef)(null);
101
105
  const pointerPressCleanupRef = (0, import_react.useRef)(null);
106
+ const toolbarDragModelUidRef = (0, import_react.useRef)(null);
102
107
  const isDraggingRef = (0, import_react.useRef)(isDragging);
103
108
  const isPointerPressActiveRef = (0, import_react.useRef)(false);
104
109
  const isToolbarDragActiveRef = (0, import_react.useRef)(false);
@@ -128,9 +133,11 @@ const DragHandler = /* @__PURE__ */ __name(({
128
133
  if (!ownerDocument) {
129
134
  return;
130
135
  }
136
+ const toolbarModelUid = getToolbarModelUidFromNode(dragHandlerRef.current) || toolbarDragModelUidRef.current || model.uid;
137
+ toolbarDragModelUidRef.current = active ? toolbarModelUid : null;
131
138
  ownerDocument.dispatchEvent(
132
139
  new CustomEvent(TOOLBAR_DRAG_ACTIVITY_EVENT, {
133
- detail: { active, modelUid: model.uid }
140
+ detail: { active, modelUid: toolbarModelUid }
134
141
  })
135
142
  );
136
143
  },
@@ -44,6 +44,7 @@ var import_react = __toESM(require("react"));
44
44
  var import_react_dom = require("react-dom");
45
45
  var import_antd = require("antd");
46
46
  var import_css = require("@emotion/css");
47
+ var import_ahooks = require("ahooks");
47
48
  var import_hooks = require("../../../../hooks");
48
49
  var import_provider = require("../../../../provider");
49
50
  var import_utils = require("../../../../utils");
@@ -312,6 +313,38 @@ const buildToolbarContainerStyle = /* @__PURE__ */ __name((portalRect, toolbarSt
312
313
  const isModelByIdProps = /* @__PURE__ */ __name((props) => {
313
314
  return "uid" in props && "modelClassName" in props && Boolean(props.uid) && Boolean(props.modelClassName);
314
315
  }, "isModelByIdProps");
316
+ const stopResizeInteractionEvent = /* @__PURE__ */ __name((event) => {
317
+ var _a;
318
+ if (!event) {
319
+ return;
320
+ }
321
+ event.preventDefault();
322
+ event.stopPropagation();
323
+ const nativeEvent = "nativeEvent" in event ? event.nativeEvent : event;
324
+ (_a = nativeEvent.stopImmediatePropagation) == null ? void 0 : _a.call(nativeEvent);
325
+ }, "stopResizeInteractionEvent");
326
+ const pendingResizeClickSuppressions = /* @__PURE__ */ new WeakMap();
327
+ const clearPendingResizeClickSuppression = /* @__PURE__ */ __name((ownerDocument) => {
328
+ const pending = pendingResizeClickSuppressions.get(ownerDocument);
329
+ if (!pending) {
330
+ return;
331
+ }
332
+ ownerDocument.removeEventListener("click", pending.listener, true);
333
+ (ownerDocument.defaultView || window).clearTimeout(pending.timer);
334
+ pendingResizeClickSuppressions.delete(ownerDocument);
335
+ }, "clearPendingResizeClickSuppression");
336
+ const suppressNextResizeClick = /* @__PURE__ */ __name((ownerDocument) => {
337
+ clearPendingResizeClickSuppression(ownerDocument);
338
+ const listener = /* @__PURE__ */ __name((event) => {
339
+ stopResizeInteractionEvent(event);
340
+ clearPendingResizeClickSuppression(ownerDocument);
341
+ }, "listener");
342
+ const timer = (ownerDocument.defaultView || window).setTimeout(() => {
343
+ clearPendingResizeClickSuppression(ownerDocument);
344
+ }, 0);
345
+ pendingResizeClickSuppressions.set(ownerDocument, { listener, timer });
346
+ ownerDocument.addEventListener("click", listener, true);
347
+ }, "suppressNextResizeClick");
315
348
  const FlowsFloatContextMenu = (0, import_reactive.observer)((props) => {
316
349
  const ctx = (0, import__.useFlowContext)();
317
350
  if (!ctx.flowSettingsEnabled) {
@@ -326,44 +359,64 @@ const ResizeHandles = /* @__PURE__ */ __name((props) => {
326
359
  const isDraggingRef = (0, import_react.useRef)(false);
327
360
  const dragTypeRef = (0, import_react.useRef)(null);
328
361
  const dragStartPosRef = (0, import_react.useRef)({ x: 0, y: 0 });
362
+ const dragOwnerDocumentRef = (0, import_react.useRef)(null);
329
363
  const { onDragStart, onDragEnd } = props;
330
- const handleDragMove = (0, import_react.useCallback)(
331
- (e) => {
332
- if (!isDraggingRef.current || !dragTypeRef.current) return;
333
- const deltaX = e.clientX - dragStartPosRef.current.x;
334
- switch (dragTypeRef.current) {
335
- case "left":
336
- props.model.parent.emitter.emit("onResizeLeft", { resizeDistance: -deltaX, model: props.model });
337
- break;
338
- case "right":
339
- props.model.parent.emitter.emit("onResizeRight", { resizeDistance: deltaX, model: props.model });
340
- break;
341
- }
342
- },
343
- [props.model]
344
- );
345
- const handleDragEnd = (0, import_react.useCallback)(() => {
364
+ const handleDragMove = (0, import_ahooks.useMemoizedFn)((e) => {
365
+ if (!isDraggingRef.current || !dragTypeRef.current) return;
366
+ stopResizeInteractionEvent(e);
367
+ const deltaX = e.clientX - dragStartPosRef.current.x;
368
+ switch (dragTypeRef.current) {
369
+ case "left":
370
+ props.model.parent.emitter.emit("onResizeLeft", { resizeDistance: -deltaX, model: props.model });
371
+ break;
372
+ case "right":
373
+ props.model.parent.emitter.emit("onResizeRight", { resizeDistance: deltaX, model: props.model });
374
+ break;
375
+ }
376
+ });
377
+ const handleDragEnd = (0, import_ahooks.useMemoizedFn)((e) => {
378
+ if (!isDraggingRef.current) {
379
+ return;
380
+ }
381
+ stopResizeInteractionEvent(e);
382
+ const ownerDocument = dragOwnerDocumentRef.current || document;
383
+ ownerDocument.removeEventListener("mousemove", handleDragMove, true);
384
+ ownerDocument.removeEventListener("mouseup", handleDragEnd, true);
385
+ suppressNextResizeClick(ownerDocument);
346
386
  isDraggingRef.current = false;
347
387
  dragTypeRef.current = null;
348
388
  dragStartPosRef.current = { x: 0, y: 0 };
349
- document.removeEventListener("mousemove", handleDragMove);
350
- document.removeEventListener("mouseup", handleDragEnd);
389
+ dragOwnerDocumentRef.current = null;
351
390
  props.model.parent.emitter.emit("onResizeEnd");
352
391
  onDragEnd == null ? void 0 : onDragEnd();
353
- }, [handleDragMove, onDragEnd, props.model]);
354
- const handleDragStart = (0, import_react.useCallback)(
355
- (e, type) => {
356
- e.preventDefault();
357
- e.stopPropagation();
358
- isDraggingRef.current = true;
359
- dragTypeRef.current = type;
360
- dragStartPosRef.current = { x: e.clientX, y: e.clientY };
361
- document.addEventListener("mousemove", handleDragMove);
362
- document.addEventListener("mouseup", handleDragEnd);
363
- onDragStart == null ? void 0 : onDragStart();
364
- },
365
- [handleDragMove, handleDragEnd, onDragStart]
366
- );
392
+ });
393
+ (0, import_react.useEffect)(() => {
394
+ return () => {
395
+ const dragOwnerDocument = dragOwnerDocumentRef.current;
396
+ dragOwnerDocument == null ? void 0 : dragOwnerDocument.removeEventListener("mousemove", handleDragMove, true);
397
+ dragOwnerDocument == null ? void 0 : dragOwnerDocument.removeEventListener("mouseup", handleDragEnd, true);
398
+ if (isDraggingRef.current) {
399
+ suppressNextResizeClick(dragOwnerDocument || document);
400
+ props.model.parent.emitter.emit("onResizeEnd");
401
+ onDragEnd == null ? void 0 : onDragEnd();
402
+ }
403
+ isDraggingRef.current = false;
404
+ dragTypeRef.current = null;
405
+ dragStartPosRef.current = { x: 0, y: 0 };
406
+ dragOwnerDocumentRef.current = null;
407
+ };
408
+ }, [handleDragMove, handleDragEnd, onDragEnd, props.model]);
409
+ const handleDragStart = (0, import_ahooks.useMemoizedFn)((e, type) => {
410
+ stopResizeInteractionEvent(e);
411
+ const ownerDocument = e.currentTarget.ownerDocument;
412
+ isDraggingRef.current = true;
413
+ dragTypeRef.current = type;
414
+ dragStartPosRef.current = { x: e.clientX, y: e.clientY };
415
+ dragOwnerDocumentRef.current = ownerDocument;
416
+ ownerDocument.addEventListener("mousemove", handleDragMove, true);
417
+ ownerDocument.addEventListener("mouseup", handleDragEnd, true);
418
+ onDragStart == null ? void 0 : onDragStart();
419
+ });
367
420
  return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(
368
421
  "div",
369
422
  {
@@ -466,6 +519,7 @@ const FlowsFloatContextMenuWithModel = (0, import_reactive.observer)(
466
519
  getPopupContainer,
467
520
  handleSettingsMenuOpenChange,
468
521
  model,
522
+ modelUid,
469
523
  settingsMenuLevel,
470
524
  showCopyUidButton,
471
525
  showDeleteButton,
@@ -44,6 +44,17 @@ const getToolbarModelUidFromTarget = /* @__PURE__ */ __name((target) => {
44
44
  }
45
45
  return ((_a = target.closest(".nb-toolbar-container[data-model-uid]")) == null ? void 0 : _a.getAttribute("data-model-uid")) || null;
46
46
  }, "getToolbarModelUidFromTarget");
47
+ const escapeCssAttributeValue = /* @__PURE__ */ __name((value) => {
48
+ return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\a ").replace(/\r/g, "\\d ").replace(/\f/g, "\\c ");
49
+ }, "escapeCssAttributeValue");
50
+ const isToolbarModelUidRendered = /* @__PURE__ */ __name((ownerDocument, modelUid) => {
51
+ if (!ownerDocument) {
52
+ return false;
53
+ }
54
+ return !!ownerDocument.querySelector(
55
+ `.nb-toolbar-container[data-model-uid="${escapeCssAttributeValue(modelUid)}"]`
56
+ );
57
+ }, "isToolbarModelUidRendered");
47
58
  const isNodeWithinDescendantFloatToolbar = /* @__PURE__ */ __name((target, container, currentModelUid) => {
48
59
  const targetModelUid = getToolbarModelUidFromTarget(target);
49
60
  if (!container || !targetModelUid || targetModelUid === currentModelUid) {
@@ -222,6 +233,15 @@ const useFloatToolbarVisibility = /* @__PURE__ */ __name(({
222
233
  const isCurrentHostTarget = !childWithMenu || childWithMenu === containerRef.current;
223
234
  if (isCurrentHostTarget) {
224
235
  clearHideToolbarTimer();
236
+ setActiveChildToolbarIds((prevIds) => {
237
+ var _a;
238
+ if (!prevIds.length) {
239
+ return prevIds;
240
+ }
241
+ const ownerDocument = ((_a = containerRef.current) == null ? void 0 : _a.ownerDocument) ?? null;
242
+ const nextIds = prevIds.filter((id) => isToolbarModelUidRendered(ownerDocument, id));
243
+ return nextIds.length === prevIds.length ? prevIds : nextIds;
244
+ });
225
245
  setHostHovered(true);
226
246
  }
227
247
  setHideMenu(!!childWithMenu && childWithMenu !== containerRef.current);
@@ -2294,6 +2294,36 @@ const _BaseFlowModelContext = class _BaseFlowModelContext extends BaseFlowEngine
2294
2294
  };
2295
2295
  __name(_BaseFlowModelContext, "BaseFlowModelContext");
2296
2296
  let BaseFlowModelContext = _BaseFlowModelContext;
2297
+ const OPEN_VIEW_INHERITED_INPUT_ARG_KEYS = [
2298
+ "dataSourceKey",
2299
+ "collectionName",
2300
+ "associationName",
2301
+ "filterByTk",
2302
+ "sourceId",
2303
+ "tabUid"
2304
+ ];
2305
+ function pickDefinedKeys(source, keys) {
2306
+ const res = {};
2307
+ for (const key of keys) {
2308
+ if (typeof (source == null ? void 0 : source[key]) !== "undefined") {
2309
+ res[key] = source[key];
2310
+ }
2311
+ }
2312
+ return res;
2313
+ }
2314
+ __name(pickDefinedKeys, "pickDefinedKeys");
2315
+ function pickDefinedOpenViewInputArgs(source) {
2316
+ return pickDefinedKeys(source, OPEN_VIEW_INHERITED_INPUT_ARG_KEYS);
2317
+ }
2318
+ __name(pickDefinedOpenViewInputArgs, "pickDefinedOpenViewInputArgs");
2319
+ function applyDefinedDefaults(target, defaults) {
2320
+ for (const [key, value] of Object.entries(defaults)) {
2321
+ if (typeof target[key] === "undefined") {
2322
+ target[key] = value;
2323
+ }
2324
+ }
2325
+ }
2326
+ __name(applyDefinedDefaults, "applyDefinedDefaults");
2297
2327
  const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContext {
2298
2328
  // public dataSourceManager: DataSourceManager;
2299
2329
  constructor(engine) {
@@ -2525,8 +2555,16 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
2525
2555
  });
2526
2556
  this.defineProperty("role", {
2527
2557
  get: /* @__PURE__ */ __name(() => {
2528
- var _a, _b;
2529
- return (_b = (_a = this.api) == null ? void 0 : _a.auth) == null ? void 0 : _b.role;
2558
+ var _a, _b, _c;
2559
+ const currentRole = (_b = (_a = this.api) == null ? void 0 : _a.auth) == null ? void 0 : _b.role;
2560
+ if (currentRole !== "__union__") {
2561
+ return currentRole;
2562
+ }
2563
+ const roles = (_c = this.user) == null ? void 0 : _c.roles;
2564
+ if (!Array.isArray(roles)) {
2565
+ return [];
2566
+ }
2567
+ return roles.map((role) => role == null ? void 0 : role.name).filter((name) => !!name);
2530
2568
  }, "get"),
2531
2569
  cache: false,
2532
2570
  // 注意:使用惰性 meta 工厂,避免在 i18n 尚未注入时提前求值导致无法翻译
@@ -2680,7 +2718,17 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
2680
2718
  doc = {};
2681
2719
  }
2682
2720
  const deprecatedCtx = createRunJSDeprecationProxy(runCtx, { doc });
2683
- const globals = { ctx: deprecatedCtx, ...(options == null ? void 0 : options.globals) || {} };
2721
+ const browserGlobals = {};
2722
+ if (typeof window !== "undefined") {
2723
+ browserGlobals.window = window;
2724
+ if (typeof navigator !== "undefined") {
2725
+ browserGlobals.navigator = navigator;
2726
+ }
2727
+ }
2728
+ if (typeof document !== "undefined") {
2729
+ browserGlobals.document = document;
2730
+ }
2731
+ const globals = { ctx: deprecatedCtx, ...browserGlobals, ...(options == null ? void 0 : options.globals) || {} };
2684
2732
  const { timeoutMs } = options || {};
2685
2733
  return new import_JSRunner.JSRunner({ globals, timeoutMs });
2686
2734
  });
@@ -2791,23 +2839,19 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
2791
2839
  }
2792
2840
  });
2793
2841
  this.defineMethod("openView", async function(uid, options) {
2794
- var _a, _b, _c, _d, _e;
2795
- const opts = { ...options };
2842
+ var _a, _b, _c, _d;
2843
+ const inheritedInputArgs = {
2844
+ ...typeof ((_a = this.model) == null ? void 0 : _a["getInputArgs"]) === "function" ? pickDefinedOpenViewInputArgs(this.model["getInputArgs"]()) : {},
2845
+ ...pickDefinedOpenViewInputArgs(this.inputArgs)
2846
+ };
2847
+ const opts = { ...options || {} };
2848
+ applyDefinedDefaults(opts, inheritedInputArgs);
2796
2849
  if (opts.defineProperties || opts.defineMethods) {
2797
2850
  opts.navigation = false;
2798
2851
  }
2799
2852
  let model2 = null;
2800
2853
  model2 = await this.engine.loadModel({ uid });
2801
2854
  if (!model2) {
2802
- const pickDefined = /* @__PURE__ */ __name((src, keys) => {
2803
- const res = {};
2804
- for (const k of keys) {
2805
- if (typeof (src == null ? void 0 : src[k]) !== "undefined") {
2806
- res[k] = src[k];
2807
- }
2808
- }
2809
- return res;
2810
- }, "pickDefined");
2811
2855
  model2 = this.engine.createModel({
2812
2856
  uid,
2813
2857
  // 注意: 新建的 model 应该使用 ${parentModel.uid}-xxx 形式的 uid
@@ -2819,7 +2863,7 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
2819
2863
  popupSettings: {
2820
2864
  openView: {
2821
2865
  // 仅在创建时持久化一份默认配置;运行时以本次 opts 为准,避免多个 opener 互相覆盖。
2822
- ...pickDefined(opts, ["dataSourceKey", "collectionName", "associationName", "mode", "size"])
2866
+ ...pickDefinedKeys(opts, ["dataSourceKey", "collectionName", "associationName", "mode", "size"])
2823
2867
  }
2824
2868
  }
2825
2869
  }
@@ -2827,12 +2871,10 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
2827
2871
  await model2.save();
2828
2872
  }
2829
2873
  model2.setParent(this.model);
2830
- const viewUid = (opts == null ? void 0 : opts.routeViewUid) ?? (opts == null ? void 0 : opts.viewUid) ?? (((_b = (_a = model2.stepParams) == null ? void 0 : _a.popupSettings) == null ? void 0 : _b.openView) ? model2.uid : this.model.uid);
2874
+ const viewUid = (opts == null ? void 0 : opts.routeViewUid) ?? (opts == null ? void 0 : opts.viewUid) ?? (((_c = (_b = model2.stepParams) == null ? void 0 : _b.popupSettings) == null ? void 0 : _c.openView) ? model2.uid : this.model.uid);
2831
2875
  const parentView = this.view;
2832
2876
  const pendingType = (opts == null ? void 0 : opts.isMobileLayout) ? "embed" : (opts == null ? void 0 : opts.mode) || "drawer";
2833
2877
  const pendingInputArgs = { ...opts, viewUid, navigation: opts.navigation };
2834
- pendingInputArgs.filterByTk = pendingInputArgs.filterByTk || ((_c = this.inputArgs) == null ? void 0 : _c.filterByTk);
2835
- pendingInputArgs.sourceId = pendingInputArgs.sourceId || ((_d = this.inputArgs) == null ? void 0 : _d.sourceId);
2836
2878
  const pendingView = {
2837
2879
  type: pendingType,
2838
2880
  inputArgs: pendingInputArgs,
@@ -2841,7 +2883,7 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
2841
2883
  engineCtx: this.engine.context
2842
2884
  };
2843
2885
  model2.context.defineProperty("view", { value: pendingView });
2844
- const popupFlow = (_e = model2.getFlow) == null ? void 0 : _e.call(model2, "popupSettings");
2886
+ const popupFlow = (_d = model2.getFlow) == null ? void 0 : _d.call(model2, "popupSettings");
2845
2887
  const on = popupFlow == null ? void 0 : popupFlow.on;
2846
2888
  let openEventName = "click";
2847
2889
  if (typeof on === "string" && on) {
@@ -2849,17 +2891,10 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
2849
2891
  } else if (on && typeof on === "object" && typeof on.eventName === "string" && on.eventName) {
2850
2892
  openEventName = on.eventName;
2851
2893
  }
2852
- await model2.dispatchEvent(
2853
- openEventName,
2854
- {
2855
- // navigation: false, // TODO: 路由模式有bug,不支持多层同样viewId的弹窗,因此这里默认先用false
2856
- // ...this.model?.['getInputArgs']?.(), // 避免部分关系字段信息丢失, 仿照 ClickableCollectionField 做法
2857
- ...opts
2858
- },
2859
- {
2860
- debounce: true
2861
- }
2862
- );
2894
+ await model2.dispatchEvent(openEventName, {
2895
+ // navigation: false, // TODO: 路由模式有bug,不支持多层同样viewId的弹窗,因此这里默认先用false
2896
+ ...opts
2897
+ });
2863
2898
  });
2864
2899
  this.defineMethod("getEvents", function() {
2865
2900
  return this.model.getEvents();
@@ -71,18 +71,25 @@ function createJSRunnerWithVersion(options) {
71
71
  doc = {};
72
72
  }
73
73
  const deprecatedCtx = (0, import_flowContext.createRunJSDeprecationProxy)(runCtx, { doc });
74
- const globals = { ctx: deprecatedCtx, ...(options == null ? void 0 : options.globals) || {} };
75
- if (modelClass === "JSFieldModel" || modelClass === "JSBlockModel") {
76
- if (typeof window !== "undefined") globals.window = window;
77
- if (typeof document !== "undefined") globals.document = document;
74
+ const browserGlobals = {};
75
+ if (typeof window !== "undefined") {
76
+ browserGlobals.window = window;
77
+ if (typeof navigator !== "undefined") {
78
+ browserGlobals.navigator = navigator;
79
+ }
78
80
  }
81
+ if (typeof document !== "undefined") {
82
+ browserGlobals.document = document;
83
+ }
84
+ const globals = { ctx: deprecatedCtx, ...browserGlobals, ...(options == null ? void 0 : options.globals) || {} };
79
85
  const { timeoutMs } = options || {};
80
86
  return new import_JSRunner.JSRunner({ globals, timeoutMs });
81
87
  }
82
88
  __name(createJSRunnerWithVersion, "createJSRunnerWithVersion");
83
89
  function getRunJSScenesForModel(modelClass, version = "v1") {
84
90
  const meta = import_registry.RunJSContextRegistry.getMeta(version, modelClass);
85
- return Array.isArray(meta == null ? void 0 : meta.scenes) ? [...meta.scenes] : [];
91
+ const scenes = meta == null ? void 0 : meta.scenes;
92
+ return Array.isArray(scenes) ? [...scenes] : [];
86
93
  }
87
94
  __name(getRunJSScenesForModel, "getRunJSScenesForModel");
88
95
  function getRunJSScenesForContext(ctx, { version = "v1" } = {}) {
@@ -21,7 +21,6 @@ export { extractPropertyPath, formatPathToVariable, isVariableExpression } from
21
21
  export { clearAutoFlowError, getAutoFlowError, setAutoFlowError, type AutoFlowError } from './autoFlowError';
22
22
  export { parsePathnameToViewParams, type ViewParam } from './parsePathnameToViewParams';
23
23
  export { decodeBase64Url, encodeBase64Url, isCompleteCtxDatePath, isCtxDatePathPrefix, isCtxDateExpression, parseCtxDateExpression, resolveCtxDatePath, serializeCtxDateValue, } from './dateVariable';
24
- export { createSafeDocument, createSafeWindow, createSafeNavigator, createSafeRunJSGlobals, runjsWithSafeGlobals, } from './safeGlobals';
25
24
  export { isRunJSValue, normalizeRunJSValue, extractUsedVariablePathsFromRunJS, type RunJSValue } from './runjsValue';
26
25
  export { resolveRunJSObjectValues } from './resolveRunJSObjectValues';
27
26
  export { prepareRunJsCode, preprocessRunJsTemplates } from './runjsTemplateCompat';
@@ -44,10 +44,6 @@ __export(utils_exports, {
44
44
  createEphemeralContext: () => import_createEphemeralContext.createEphemeralContext,
45
45
  createRecordMetaFactory: () => import_variablesParams.createRecordMetaFactory,
46
46
  createRecordResolveOnServerWithLocal: () => import_variablesParams.createRecordResolveOnServerWithLocal,
47
- createSafeDocument: () => import_safeGlobals.createSafeDocument,
48
- createSafeNavigator: () => import_safeGlobals.createSafeNavigator,
49
- createSafeRunJSGlobals: () => import_safeGlobals.createSafeRunJSGlobals,
50
- createSafeWindow: () => import_safeGlobals.createSafeWindow,
51
47
  decodeBase64Url: () => import_dateVariable.decodeBase64Url,
52
48
  defineAction: () => import_flow_definitions.defineAction,
53
49
  encodeBase64Url: () => import_dateVariable.encodeBase64Url,
@@ -84,7 +80,6 @@ __export(utils_exports, {
84
80
  resolveStepDisabledInSettings: () => import_schema_utils.resolveStepDisabledInSettings,
85
81
  resolveStepUiSchema: () => import_schema_utils.resolveStepUiSchema,
86
82
  resolveUiMode: () => import_schema_utils.resolveUiMode,
87
- runjsWithSafeGlobals: () => import_safeGlobals.runjsWithSafeGlobals,
88
83
  serializeCtxDateValue: () => import_dateVariable.serializeCtxDateValue,
89
84
  setAutoFlowError: () => import_autoFlowError.setAutoFlowError,
90
85
  setupRuntimeContextSteps: () => import_setupRuntimeContextSteps.setupRuntimeContextSteps,
@@ -108,7 +103,6 @@ var import_context = require("./context");
108
103
  var import_autoFlowError = require("./autoFlowError");
109
104
  var import_parsePathnameToViewParams = require("./parsePathnameToViewParams");
110
105
  var import_dateVariable = require("./dateVariable");
111
- var import_safeGlobals = require("./safeGlobals");
112
106
  var import_runjsValue = require("./runjsValue");
113
107
  var import_resolveRunJSObjectValues = require("./resolveRunJSObjectValues");
114
108
  var import_runjsTemplateCompat = require("./runjsTemplateCompat");
@@ -137,10 +131,6 @@ var import_randomId = require("./randomId");
137
131
  createEphemeralContext,
138
132
  createRecordMetaFactory,
139
133
  createRecordResolveOnServerWithLocal,
140
- createSafeDocument,
141
- createSafeNavigator,
142
- createSafeRunJSGlobals,
143
- createSafeWindow,
144
134
  decodeBase64Url,
145
135
  defineAction,
146
136
  encodeBase64Url,
@@ -177,7 +167,6 @@ var import_randomId = require("./randomId");
177
167
  resolveStepDisabledInSettings,
178
168
  resolveStepUiSchema,
179
169
  resolveUiMode,
180
- runjsWithSafeGlobals,
181
170
  serializeCtxDateValue,
182
171
  setAutoFlowError,
183
172
  setupRuntimeContextSteps,
@@ -31,8 +31,8 @@ __export(resolveRunJSObjectValues_exports, {
31
31
  });
32
32
  module.exports = __toCommonJS(resolveRunJSObjectValues_exports);
33
33
  var import_runjsValue = require("./runjsValue");
34
- var import_safeGlobals = require("./safeGlobals");
35
34
  async function resolveRunJSObjectValues(ctx, raw) {
35
+ var _a;
36
36
  const out = {};
37
37
  if (!raw || typeof raw !== "object") return out;
38
38
  if (Array.isArray(raw)) return out;
@@ -41,7 +41,8 @@ async function resolveRunJSObjectValues(ctx, raw) {
41
41
  if ((0, import_runjsValue.isRunJSValue)(value)) {
42
42
  const { code, version } = (0, import_runjsValue.normalizeRunJSValue)(value);
43
43
  if (!code.trim()) continue;
44
- const ret = await (0, import_safeGlobals.runjsWithSafeGlobals)(ctx, code, { version });
44
+ const runjsCtx = ctx;
45
+ const ret = await ((_a = runjsCtx == null ? void 0 : runjsCtx.runjs) == null ? void 0 : _a.call(runjsCtx, code, void 0, { version }));
45
46
  if (!(ret == null ? void 0 : ret.success)) {
46
47
  throw new Error(`RunJS execution failed for "${key}"`);
47
48
  }