@ant-design/agentic-ui 2.0.21 → 2.0.23
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/dist/Bubble/FileView.js +27 -31
- package/dist/Bubble/MessagesContent/VoiceButton/style.js +6 -3
- package/dist/ChatBootPage/ButtonTabStyle.js +2 -0
- package/dist/ChatBootPage/CaseReply.d.ts +0 -3
- package/dist/ChatBootPage/CaseReplyStyle.js +3 -4
- package/dist/Components/ActionIconBox/style.js +3 -1
- package/dist/Components/GradientText/index.d.ts +2 -1
- package/dist/Components/GradientText/index.js +3 -2
- package/dist/Components/GradientText/style.js +3 -8
- package/dist/Components/TextAnimate/index.d.ts +1 -0
- package/dist/Components/TextAnimate/index.js +27 -16
- package/dist/Components/TypingAnimation/index.d.ts +1 -1
- package/dist/Components/TypingAnimation/index.js +9 -9
- package/dist/Components/lotties/LoadingLottie/loading.json +1989 -1
- package/dist/Components/lotties/{ShinyText → TextLoading}/index.d.ts +9 -9
- package/dist/Components/lotties/{ShinyText → TextLoading}/index.js +7 -7
- package/dist/Components/lotties/{ShinyText → TextLoading}/style.js +4 -4
- package/dist/Components/lotties/index.d.ts +1 -1
- package/dist/Components/lotties/index.js +1 -1
- package/dist/History/components/HistoryItem.js +14 -6
- package/dist/History/types/HistoryData.d.ts +2 -0
- package/dist/MarkdownEditor/editor/components/ContributorAvatar/index.js +1 -1
- package/dist/MarkdownEditor/editor/components/LazyElement/index.js +36 -4
- package/dist/MarkdownEditor/editor/elements/Table/TableRowIndex/index.js +3 -1
- package/dist/MarkdownEditor/editor/elements/TagPopup/index.js +6 -3
- package/dist/MarkdownEditor/editor/elements/TagPopup/style.js +5 -1
- package/dist/MarkdownEditor/editor/parser/parserMarkdownToSlateNode.d.ts +4 -0
- package/dist/MarkdownEditor/editor/parser/parserMarkdownToSlateNode.js +245 -344
- package/dist/MarkdownEditor/editor/parser/parserSlateNodeToMarkdown.js +74 -56
- package/dist/MarkdownEditor/editor/store.d.ts +36 -0
- package/dist/MarkdownEditor/editor/store.js +208 -76
- package/dist/MarkdownInputField/AttachmentButton/style.js +1 -1
- package/dist/MarkdownInputField/BeforeToolContainer/BeforeToolContainer.js +2 -1
- package/dist/MarkdownInputField/MarkdownInputField.js +1 -1
- package/dist/MarkdownInputField/VoiceInput/style.js +1 -1
- package/dist/MarkdownInputField/style.js +2 -8
- package/dist/Plugins/chart/DonutChart/style.js +1 -0
- package/dist/Plugins/chart/LineChart/index.js +66 -55
- package/dist/Plugins/chart/LineChart/style.js +8 -0
- package/dist/Schema/SchemaRenderer/index.js +81 -56
- package/dist/Utils/proxySandbox/ProxySandbox.d.ts +32 -0
- package/dist/Utils/proxySandbox/ProxySandbox.js +176 -128
- package/dist/WelcomeMessage/index.d.ts +2 -2
- package/dist/WelcomeMessage/index.js +8 -5
- package/dist/WelcomeMessage/style.js +0 -1
- package/package.json +1 -1
- /package/dist/Components/lotties/{ShinyText → TextLoading}/style.d.ts +0 -0
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
PointElement,
|
|
43
43
|
Tooltip
|
|
44
44
|
} from "chart.js";
|
|
45
|
+
import classNames from "classnames";
|
|
45
46
|
import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
46
47
|
import { Line } from "react-chartjs-2";
|
|
47
48
|
import {
|
|
@@ -56,6 +57,7 @@ import {
|
|
|
56
57
|
extractAndSortXValues,
|
|
57
58
|
findDataPointByXValue
|
|
58
59
|
} from "../utils";
|
|
60
|
+
import { useStyle } from "./style";
|
|
59
61
|
ChartJS.register(
|
|
60
62
|
CategoryScale,
|
|
61
63
|
LinearScale,
|
|
@@ -125,6 +127,7 @@ var LineChart = (_a) => {
|
|
|
125
127
|
}, []);
|
|
126
128
|
const context = useContext(ConfigProvider.ConfigContext);
|
|
127
129
|
const baseClassName = context == null ? void 0 : context.getPrefixCls("line-chart-container");
|
|
130
|
+
const { wrapSSR, hashId } = useStyle(baseClassName);
|
|
128
131
|
const chartRef = useRef(null);
|
|
129
132
|
const statistics = useMemo(() => {
|
|
130
133
|
if (!statisticConfig)
|
|
@@ -325,65 +328,73 @@ var LineChart = (_a) => {
|
|
|
325
328
|
const handleDownload = () => {
|
|
326
329
|
downloadChart(chartRef.current, "line-chart");
|
|
327
330
|
};
|
|
328
|
-
return
|
|
329
|
-
ChartContainer,
|
|
330
|
-
{
|
|
331
|
-
baseClassName,
|
|
332
|
-
className,
|
|
333
|
-
theme,
|
|
334
|
-
isMobile,
|
|
335
|
-
variant: props.variant,
|
|
336
|
-
style: {
|
|
337
|
-
width: responsiveWidth
|
|
338
|
-
}
|
|
339
|
-
},
|
|
331
|
+
return wrapSSR(
|
|
340
332
|
/* @__PURE__ */ React.createElement(
|
|
341
|
-
|
|
333
|
+
ChartContainer,
|
|
342
334
|
{
|
|
343
|
-
|
|
335
|
+
baseClassName,
|
|
336
|
+
className,
|
|
344
337
|
theme,
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
__spreadProps(__spreadValues({
|
|
351
|
-
filterOptions,
|
|
352
|
-
selectedFilter,
|
|
353
|
-
onFilterChange: setSelectedFilter
|
|
354
|
-
}, filterLabels && {
|
|
355
|
-
customOptions: filteredDataByFilterLabel,
|
|
356
|
-
selectedCustomSelection: selectedFilterLabel,
|
|
357
|
-
onSelectionChange: setSelectedFilterLabel
|
|
358
|
-
}), {
|
|
359
|
-
theme,
|
|
360
|
-
variant: "compact"
|
|
361
|
-
})
|
|
362
|
-
) : void 0
|
|
363
|
-
}
|
|
364
|
-
),
|
|
365
|
-
statistics && /* @__PURE__ */ React.createElement("div", { className: `${baseClassName}-statistic-container` }, statistics.map((config, index) => /* @__PURE__ */ React.createElement(ChartStatistic, __spreadProps(__spreadValues({ key: index }, config), { theme })))),
|
|
366
|
-
!renderFilterInToolbar && filterOptions && filterOptions.length > 1 && /* @__PURE__ */ React.createElement(
|
|
367
|
-
ChartFilter,
|
|
368
|
-
__spreadProps(__spreadValues({
|
|
369
|
-
filterOptions,
|
|
370
|
-
selectedFilter,
|
|
371
|
-
onFilterChange: setSelectedFilter
|
|
372
|
-
}, filterLabels && {
|
|
373
|
-
customOptions: filteredDataByFilterLabel,
|
|
374
|
-
selectedCustomSelection: selectedFilterLabel,
|
|
375
|
-
onSelectionChange: setSelectedFilterLabel
|
|
376
|
-
}), {
|
|
377
|
-
theme
|
|
378
|
-
})
|
|
379
|
-
),
|
|
380
|
-
/* @__PURE__ */ React.createElement(
|
|
381
|
-
"div",
|
|
382
|
-
{
|
|
383
|
-
className: `${baseClassName}-wrapper`,
|
|
384
|
-
style: { height: responsiveHeight }
|
|
338
|
+
isMobile,
|
|
339
|
+
variant: props.variant,
|
|
340
|
+
style: {
|
|
341
|
+
width: responsiveWidth
|
|
342
|
+
}
|
|
385
343
|
},
|
|
386
|
-
/* @__PURE__ */ React.createElement(
|
|
344
|
+
/* @__PURE__ */ React.createElement(
|
|
345
|
+
ChartToolBar,
|
|
346
|
+
{
|
|
347
|
+
title,
|
|
348
|
+
theme,
|
|
349
|
+
onDownload: handleDownload,
|
|
350
|
+
extra: toolbarExtra,
|
|
351
|
+
dataTime,
|
|
352
|
+
filter: renderFilterInToolbar && filterOptions && filterOptions.length > 1 ? /* @__PURE__ */ React.createElement(
|
|
353
|
+
ChartFilter,
|
|
354
|
+
__spreadProps(__spreadValues({
|
|
355
|
+
filterOptions,
|
|
356
|
+
selectedFilter,
|
|
357
|
+
onFilterChange: setSelectedFilter
|
|
358
|
+
}, filterLabels && {
|
|
359
|
+
customOptions: filteredDataByFilterLabel,
|
|
360
|
+
selectedCustomSelection: selectedFilterLabel,
|
|
361
|
+
onSelectionChange: setSelectedFilterLabel
|
|
362
|
+
}), {
|
|
363
|
+
theme,
|
|
364
|
+
variant: "compact"
|
|
365
|
+
})
|
|
366
|
+
) : void 0
|
|
367
|
+
}
|
|
368
|
+
),
|
|
369
|
+
statistics && /* @__PURE__ */ React.createElement(
|
|
370
|
+
"div",
|
|
371
|
+
{
|
|
372
|
+
className: classNames(`${baseClassName}-statistic-container`, hashId)
|
|
373
|
+
},
|
|
374
|
+
statistics.map((config, index) => /* @__PURE__ */ React.createElement(ChartStatistic, __spreadProps(__spreadValues({ key: index }, config), { theme })))
|
|
375
|
+
),
|
|
376
|
+
!renderFilterInToolbar && filterOptions && filterOptions.length > 1 && /* @__PURE__ */ React.createElement(
|
|
377
|
+
ChartFilter,
|
|
378
|
+
__spreadProps(__spreadValues({
|
|
379
|
+
filterOptions,
|
|
380
|
+
selectedFilter,
|
|
381
|
+
onFilterChange: setSelectedFilter
|
|
382
|
+
}, filterLabels && {
|
|
383
|
+
customOptions: filteredDataByFilterLabel,
|
|
384
|
+
selectedCustomSelection: selectedFilterLabel,
|
|
385
|
+
onSelectionChange: setSelectedFilterLabel
|
|
386
|
+
}), {
|
|
387
|
+
theme
|
|
388
|
+
})
|
|
389
|
+
),
|
|
390
|
+
/* @__PURE__ */ React.createElement(
|
|
391
|
+
"div",
|
|
392
|
+
{
|
|
393
|
+
className: `${baseClassName}-wrapper`,
|
|
394
|
+
style: { height: responsiveHeight }
|
|
395
|
+
},
|
|
396
|
+
/* @__PURE__ */ React.createElement(Line, { ref: chartRef, data: processedData, options })
|
|
397
|
+
)
|
|
387
398
|
)
|
|
388
399
|
);
|
|
389
400
|
};
|
|
@@ -26,6 +26,14 @@ var genStyle = (token) => {
|
|
|
26
26
|
return {
|
|
27
27
|
[token.componentCls]: {
|
|
28
28
|
// 折线图容器样式
|
|
29
|
+
// 统计数据容器样式
|
|
30
|
+
"&-statistic-container": {
|
|
31
|
+
display: "flex",
|
|
32
|
+
gap: "16px",
|
|
33
|
+
marginBottom: "16px",
|
|
34
|
+
flexWrap: "wrap",
|
|
35
|
+
alignItems: "flex-start"
|
|
36
|
+
},
|
|
29
37
|
".chart-wrapper": {
|
|
30
38
|
width: "100%",
|
|
31
39
|
height: "calc(100% - 120px)",
|
|
@@ -49,13 +49,92 @@ import React, {
|
|
|
49
49
|
useState
|
|
50
50
|
} from "react";
|
|
51
51
|
import partialParse from "../../MarkdownEditor/editor/parser/json-parse";
|
|
52
|
-
import { mdDataSchemaValidator } from "../validator";
|
|
53
52
|
import {
|
|
54
53
|
createSandbox,
|
|
55
54
|
DEFAULT_SANDBOX_CONFIG
|
|
56
55
|
} from "../../Utils/proxySandbox";
|
|
56
|
+
import { mdDataSchemaValidator } from "../validator";
|
|
57
57
|
import { TemplateEngine } from "./templateEngine";
|
|
58
58
|
export * from "./templateEngine";
|
|
59
|
+
var createSandboxInstance = (sandboxConfig) => {
|
|
60
|
+
var _a, _b;
|
|
61
|
+
return createSandbox(__spreadProps(__spreadValues({}, DEFAULT_SANDBOX_CONFIG), {
|
|
62
|
+
allowDOM: (_a = sandboxConfig.allowDOM) != null ? _a : true,
|
|
63
|
+
allowedGlobals: sandboxConfig.allowedGlobals || DEFAULT_SANDBOX_CONFIG.allowedGlobals,
|
|
64
|
+
forbiddenGlobals: sandboxConfig.forbiddenGlobals || DEFAULT_SANDBOX_CONFIG.forbiddenGlobals,
|
|
65
|
+
strictMode: (_b = sandboxConfig.strictMode) != null ? _b : true,
|
|
66
|
+
timeout: sandboxConfig.timeout || 3e3
|
|
67
|
+
}));
|
|
68
|
+
};
|
|
69
|
+
var createSandboxContext = (shadowRoot) => {
|
|
70
|
+
return {
|
|
71
|
+
shadowRoot,
|
|
72
|
+
safeWindow: {
|
|
73
|
+
devicePixelRatio: typeof window !== "undefined" ? window.devicePixelRatio : 1,
|
|
74
|
+
innerWidth: typeof window !== "undefined" ? window.innerWidth : 1024,
|
|
75
|
+
innerHeight: typeof window !== "undefined" ? window.innerHeight : 768
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
var executeUnsafeScript = (script, shadowRoot) => {
|
|
80
|
+
console.warn("沙箱已禁用,使用不安全的脚本执行方式");
|
|
81
|
+
const scriptFn = new Function(
|
|
82
|
+
"shadowRoot",
|
|
83
|
+
"window",
|
|
84
|
+
script.textContent || ""
|
|
85
|
+
);
|
|
86
|
+
try {
|
|
87
|
+
scriptFn(shadowRoot, {
|
|
88
|
+
devicePixelRatio: window.devicePixelRatio
|
|
89
|
+
});
|
|
90
|
+
} catch (evalError) {
|
|
91
|
+
console.error("执行脚本错误:", evalError);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
var executeExternalScript = (script, shadowRoot) => {
|
|
95
|
+
console.warn("外部脚本暂时不通过沙箱执行:", script.src);
|
|
96
|
+
try {
|
|
97
|
+
shadowRoot == null ? void 0 : shadowRoot.appendChild(script);
|
|
98
|
+
} catch (appendError) {
|
|
99
|
+
console.error("Error appending external script:", appendError);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var executeSandboxedScript = (script, shadowRoot, sandboxConfig) => __async(void 0, null, function* () {
|
|
103
|
+
const sandbox = createSandboxInstance(sandboxConfig);
|
|
104
|
+
try {
|
|
105
|
+
const result = yield sandbox.execute(
|
|
106
|
+
script.textContent || "",
|
|
107
|
+
createSandboxContext(shadowRoot)
|
|
108
|
+
);
|
|
109
|
+
if (!result.success && result.error) {
|
|
110
|
+
console.error("沙箱脚本执行错误:", result.error);
|
|
111
|
+
}
|
|
112
|
+
} catch (evalError) {
|
|
113
|
+
console.error("沙箱执行失败:", evalError);
|
|
114
|
+
} finally {
|
|
115
|
+
sandbox.destroy();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
var executeInlineScript = (script, shadowRoot, sandboxConfig) => __async(void 0, null, function* () {
|
|
119
|
+
if (!sandboxConfig.enabled) {
|
|
120
|
+
executeUnsafeScript(script, shadowRoot);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
yield executeSandboxedScript(script, shadowRoot, sandboxConfig);
|
|
124
|
+
});
|
|
125
|
+
var executeScript = (script, shadowRoot, sandboxConfig) => __async(void 0, null, function* () {
|
|
126
|
+
try {
|
|
127
|
+
if (!script.src && script.textContent) {
|
|
128
|
+
yield executeInlineScript(script, shadowRoot, sandboxConfig);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (script.src) {
|
|
132
|
+
executeExternalScript(script, shadowRoot);
|
|
133
|
+
}
|
|
134
|
+
} catch (scriptError) {
|
|
135
|
+
console.error("Script execution error:", scriptError);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
59
138
|
var ErrorBoundary = class extends Component {
|
|
60
139
|
constructor(props) {
|
|
61
140
|
super(props);
|
|
@@ -354,61 +433,7 @@ a:active {
|
|
|
354
433
|
}
|
|
355
434
|
});
|
|
356
435
|
scripts.forEach((script) => __async(void 0, null, function* () {
|
|
357
|
-
|
|
358
|
-
try {
|
|
359
|
-
if (!script.src && script.textContent) {
|
|
360
|
-
if (sandboxConfig.enabled) {
|
|
361
|
-
const sandbox = createSandbox(__spreadProps(__spreadValues({}, DEFAULT_SANDBOX_CONFIG), {
|
|
362
|
-
allowDOM: (_a2 = sandboxConfig.allowDOM) != null ? _a2 : true,
|
|
363
|
-
allowedGlobals: sandboxConfig.allowedGlobals || DEFAULT_SANDBOX_CONFIG.allowedGlobals,
|
|
364
|
-
forbiddenGlobals: sandboxConfig.forbiddenGlobals || DEFAULT_SANDBOX_CONFIG.forbiddenGlobals,
|
|
365
|
-
strictMode: (_b2 = sandboxConfig.strictMode) != null ? _b2 : true,
|
|
366
|
-
timeout: sandboxConfig.timeout || 3e3
|
|
367
|
-
}));
|
|
368
|
-
try {
|
|
369
|
-
const result = yield sandbox.execute(script.textContent, {
|
|
370
|
-
shadowRoot,
|
|
371
|
-
// 提供一个安全的 window 上下文
|
|
372
|
-
safeWindow: {
|
|
373
|
-
devicePixelRatio: typeof window !== "undefined" ? window.devicePixelRatio : 1,
|
|
374
|
-
innerWidth: typeof window !== "undefined" ? window.innerWidth : 1024,
|
|
375
|
-
innerHeight: typeof window !== "undefined" ? window.innerHeight : 768
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
if (!result.success && result.error) {
|
|
379
|
-
console.error("沙箱脚本执行错误:", result.error);
|
|
380
|
-
}
|
|
381
|
-
} catch (evalError) {
|
|
382
|
-
console.error("沙箱执行失败:", evalError);
|
|
383
|
-
} finally {
|
|
384
|
-
sandbox.destroy();
|
|
385
|
-
}
|
|
386
|
-
} else {
|
|
387
|
-
console.warn("沙箱已禁用,使用不安全的脚本执行方式");
|
|
388
|
-
const scriptFn = new Function(
|
|
389
|
-
"shadowRoot",
|
|
390
|
-
"window",
|
|
391
|
-
script.textContent
|
|
392
|
-
);
|
|
393
|
-
try {
|
|
394
|
-
scriptFn(shadowRoot, {
|
|
395
|
-
devicePixelRatio: window.devicePixelRatio
|
|
396
|
-
});
|
|
397
|
-
} catch (evalError) {
|
|
398
|
-
console.error("执行脚本错误:", evalError);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
} else if (script.src) {
|
|
402
|
-
console.warn("外部脚本暂时不通过沙箱执行:", script.src);
|
|
403
|
-
try {
|
|
404
|
-
shadowRoot == null ? void 0 : shadowRoot.appendChild(script);
|
|
405
|
-
} catch (appendError) {
|
|
406
|
-
console.error("Error appending external script:", appendError);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
} catch (scriptError) {
|
|
410
|
-
console.error("Script execution error:", scriptError);
|
|
411
|
-
}
|
|
436
|
+
yield executeScript(script, shadowRoot, sandboxConfig);
|
|
412
437
|
}));
|
|
413
438
|
} catch (contentError) {
|
|
414
439
|
console.error("Error processing content:", contentError);
|
|
@@ -117,6 +117,38 @@ export declare class ProxySandbox {
|
|
|
117
117
|
* 使用 Worker 执行代码以实现真正的超时控制
|
|
118
118
|
*/
|
|
119
119
|
private executeWithWorker;
|
|
120
|
+
/**
|
|
121
|
+
* 尝试序列化参数,失败则回退到同步执行
|
|
122
|
+
*/
|
|
123
|
+
private trySerializeParams;
|
|
124
|
+
/**
|
|
125
|
+
* 回退到同步执行
|
|
126
|
+
*/
|
|
127
|
+
private fallbackToSyncExecution;
|
|
128
|
+
/**
|
|
129
|
+
* 创建 Worker 实例
|
|
130
|
+
*/
|
|
131
|
+
private createWorkerInstance;
|
|
132
|
+
/**
|
|
133
|
+
* 生成 Worker 代码
|
|
134
|
+
*/
|
|
135
|
+
private generateWorkerCode;
|
|
136
|
+
/**
|
|
137
|
+
* 设置 Worker 超时
|
|
138
|
+
*/
|
|
139
|
+
private setupWorkerTimeout;
|
|
140
|
+
/**
|
|
141
|
+
* 设置 Worker 消息处理器
|
|
142
|
+
*/
|
|
143
|
+
private setupWorkerHandlers;
|
|
144
|
+
/**
|
|
145
|
+
* 处理控制台消息
|
|
146
|
+
*/
|
|
147
|
+
private handleConsoleMessage;
|
|
148
|
+
/**
|
|
149
|
+
* 清理 Worker 资源
|
|
150
|
+
*/
|
|
151
|
+
private cleanupWorker;
|
|
120
152
|
/**
|
|
121
153
|
* 执行代码的核心方法(同步版本)
|
|
122
154
|
*/
|
|
@@ -732,140 +732,188 @@ ${instrumented}`;
|
|
|
732
732
|
*/
|
|
733
733
|
executeWithWorker(code, injectedParams) {
|
|
734
734
|
return new Promise((resolve, reject) => {
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
735
|
+
const serializableParams = this.trySerializeParams(
|
|
736
|
+
injectedParams,
|
|
737
|
+
code,
|
|
738
|
+
resolve,
|
|
739
|
+
reject
|
|
740
|
+
);
|
|
741
|
+
if (!serializableParams)
|
|
742
|
+
return;
|
|
743
|
+
const { worker, workerUrl, timeoutId } = this.createWorkerInstance(
|
|
744
|
+
code,
|
|
745
|
+
serializableParams,
|
|
746
|
+
resolve,
|
|
747
|
+
reject
|
|
748
|
+
);
|
|
749
|
+
if (!worker)
|
|
750
|
+
return;
|
|
751
|
+
this.setupWorkerHandlers(
|
|
752
|
+
worker,
|
|
753
|
+
workerUrl,
|
|
754
|
+
timeoutId,
|
|
755
|
+
resolve,
|
|
756
|
+
reject
|
|
757
|
+
);
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* 尝试序列化参数,失败则回退到同步执行
|
|
762
|
+
*/
|
|
763
|
+
trySerializeParams(injectedParams, code, resolve, reject) {
|
|
764
|
+
if (!injectedParams)
|
|
765
|
+
return {};
|
|
766
|
+
const serializableParams = {};
|
|
767
|
+
for (const [key, value] of Object.entries(injectedParams)) {
|
|
768
|
+
try {
|
|
769
|
+
JSON.stringify(value);
|
|
770
|
+
serializableParams[key] = value;
|
|
771
|
+
} catch (e) {
|
|
772
|
+
console.warn(`无法序列化注入参数 "${key}",回退到同步执行`);
|
|
773
|
+
this.fallbackToSyncExecution(code, injectedParams, resolve, reject);
|
|
774
|
+
return null;
|
|
758
775
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
776
|
+
}
|
|
777
|
+
return serializableParams;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* 回退到同步执行
|
|
781
|
+
*/
|
|
782
|
+
fallbackToSyncExecution(code, injectedParams, resolve, reject) {
|
|
783
|
+
try {
|
|
784
|
+
const result = this.executeCode(code, injectedParams);
|
|
785
|
+
resolve(result);
|
|
786
|
+
} catch (error) {
|
|
787
|
+
reject(error);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* 创建 Worker 实例
|
|
792
|
+
*/
|
|
793
|
+
createWorkerInstance(code, serializableParams, resolve, reject) {
|
|
794
|
+
const workerCode = this.generateWorkerCode();
|
|
795
|
+
const blob = new Blob([workerCode], { type: "application/javascript" });
|
|
796
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
797
|
+
try {
|
|
798
|
+
const worker = new Worker(workerUrl);
|
|
799
|
+
const timeoutId = this.setupWorkerTimeout(worker, workerUrl, reject);
|
|
800
|
+
worker.postMessage({
|
|
801
|
+
code,
|
|
802
|
+
config: this.config,
|
|
803
|
+
injectedParams: serializableParams
|
|
804
|
+
});
|
|
805
|
+
return { worker, workerUrl, timeoutId };
|
|
806
|
+
} catch (error) {
|
|
807
|
+
URL.revokeObjectURL(workerUrl);
|
|
808
|
+
console.warn("Worker 创建失败,回退到同步执行");
|
|
809
|
+
this.fallbackToSyncExecution(code, serializableParams, resolve, reject);
|
|
810
|
+
return { worker: null, workerUrl, timeoutId: 0 };
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* 生成 Worker 代码
|
|
815
|
+
*/
|
|
816
|
+
generateWorkerCode() {
|
|
817
|
+
return `
|
|
818
|
+
self.onmessage = function(e) {
|
|
819
|
+
const { code, config, injectedParams } = e.data;
|
|
820
|
+
|
|
821
|
+
try {
|
|
822
|
+
// 创建安全的执行环境
|
|
823
|
+
const safeGlobals = {
|
|
824
|
+
Math, Date, JSON, parseInt, parseFloat, isNaN, isFinite,
|
|
825
|
+
encodeURIComponent, decodeURIComponent, encodeURI, decodeURI,
|
|
826
|
+
String, Number, Boolean, Array, Object, RegExp,
|
|
827
|
+
Error, TypeError, ReferenceError, SyntaxError
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
// 添加自定义全局变量
|
|
831
|
+
Object.assign(safeGlobals, config.customGlobals || {});
|
|
832
|
+
|
|
833
|
+
// 添加注入的参数
|
|
834
|
+
Object.assign(safeGlobals, injectedParams || {});
|
|
762
835
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
836
|
+
// 添加 console(如果允许)
|
|
837
|
+
if (config.allowConsole) {
|
|
838
|
+
safeGlobals.console = {
|
|
839
|
+
log: (...args) => self.postMessage({ type: 'log', data: args }),
|
|
840
|
+
warn: (...args) => self.postMessage({ type: 'warn', data: args }),
|
|
841
|
+
error: (...args) => self.postMessage({ type: 'error', data: args }),
|
|
842
|
+
info: (...args) => self.postMessage({ type: 'info', data: args }),
|
|
843
|
+
debug: (...args) => self.postMessage({ type: 'debug', data: args })
|
|
770
844
|
};
|
|
771
|
-
|
|
772
|
-
// 添加自定义全局变量
|
|
773
|
-
Object.assign(safeGlobals, config.customGlobals || {});
|
|
774
|
-
|
|
775
|
-
// 添加注入的参数
|
|
776
|
-
Object.assign(safeGlobals, injectedParams || {});
|
|
777
|
-
|
|
778
|
-
// 添加 console(如果允许)
|
|
779
|
-
if (config.allowConsole) {
|
|
780
|
-
safeGlobals.console = {
|
|
781
|
-
log: (...args) => self.postMessage({ type: 'log', data: args }),
|
|
782
|
-
warn: (...args) => self.postMessage({ type: 'warn', data: args }),
|
|
783
|
-
error: (...args) => self.postMessage({ type: 'error', data: args }),
|
|
784
|
-
info: (...args) => self.postMessage({ type: 'info', data: args }),
|
|
785
|
-
debug: (...args) => self.postMessage({ type: 'debug', data: args })
|
|
786
|
-
};
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
// 创建执行函数
|
|
790
|
-
const wrappedCode = config.strictMode ? "'use strict';\\n" + code : code;
|
|
791
|
-
const func = new Function(...Object.keys(safeGlobals), 'return (function() { ' + wrappedCode + ' })()');
|
|
792
|
-
|
|
793
|
-
// 执行代码
|
|
794
|
-
const result = func(...Object.values(safeGlobals));
|
|
795
|
-
|
|
796
|
-
self.postMessage({ type: 'result', data: result });
|
|
797
|
-
} catch (error) {
|
|
798
|
-
self.postMessage({ type: 'error', data: { message: error.message, stack: error.stack } });
|
|
799
|
-
}
|
|
800
|
-
};
|
|
801
|
-
`;
|
|
802
|
-
const blob = new Blob([workerCode], { type: "application/javascript" });
|
|
803
|
-
const workerUrl = URL.createObjectURL(blob);
|
|
804
|
-
let worker;
|
|
805
|
-
let timeoutId;
|
|
806
|
-
try {
|
|
807
|
-
worker = new Worker(workerUrl);
|
|
808
|
-
timeoutId = window.setTimeout(() => {
|
|
809
|
-
if (worker) {
|
|
810
|
-
worker.terminate();
|
|
811
845
|
}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
);
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
const
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
worker.terminate();
|
|
824
|
-
URL.revokeObjectURL(workerUrl);
|
|
825
|
-
resolve(data);
|
|
826
|
-
} else if (type === "error") {
|
|
827
|
-
if (timeoutId)
|
|
828
|
-
clearTimeout(timeoutId);
|
|
829
|
-
if (worker)
|
|
830
|
-
worker.terminate();
|
|
831
|
-
URL.revokeObjectURL(workerUrl);
|
|
832
|
-
reject(new Error(data.message));
|
|
833
|
-
} else if (type === "log" || type === "warn" || type === "error" || type === "info" || type === "debug") {
|
|
834
|
-
if (this.config.allowConsole) {
|
|
835
|
-
const consoleMethod = console[type];
|
|
836
|
-
if (typeof consoleMethod === "function") {
|
|
837
|
-
consoleMethod("[Sandbox]", ...data);
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
};
|
|
842
|
-
worker.onerror = (error) => {
|
|
843
|
-
if (timeoutId)
|
|
844
|
-
clearTimeout(timeoutId);
|
|
845
|
-
if (worker)
|
|
846
|
-
worker.terminate();
|
|
847
|
-
URL.revokeObjectURL(workerUrl);
|
|
848
|
-
reject(new Error(`Worker error: ${error.message}`));
|
|
849
|
-
};
|
|
850
|
-
worker.postMessage({
|
|
851
|
-
code,
|
|
852
|
-
config: this.config,
|
|
853
|
-
injectedParams: serializableParams
|
|
854
|
-
});
|
|
855
|
-
} catch (error) {
|
|
856
|
-
if (timeoutId)
|
|
857
|
-
clearTimeout(timeoutId);
|
|
858
|
-
if (worker)
|
|
859
|
-
worker.terminate();
|
|
860
|
-
URL.revokeObjectURL(workerUrl);
|
|
861
|
-
try {
|
|
862
|
-
const result = this.executeCode(code, injectedParams);
|
|
863
|
-
resolve(result);
|
|
864
|
-
} catch (syncError) {
|
|
865
|
-
reject(syncError);
|
|
846
|
+
|
|
847
|
+
// 创建执行函数
|
|
848
|
+
const wrappedCode = config.strictMode ? "'use strict';\\n" + code : code;
|
|
849
|
+
const func = new Function(...Object.keys(safeGlobals), 'return (function() { ' + wrappedCode + ' })()');
|
|
850
|
+
|
|
851
|
+
// 执行代码
|
|
852
|
+
const result = func(...Object.values(safeGlobals));
|
|
853
|
+
|
|
854
|
+
self.postMessage({ type: 'result', data: result });
|
|
855
|
+
} catch (error) {
|
|
856
|
+
self.postMessage({ type: 'error', data: { message: error.message, stack: error.stack } });
|
|
866
857
|
}
|
|
858
|
+
};
|
|
859
|
+
`;
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* 设置 Worker 超时
|
|
863
|
+
*/
|
|
864
|
+
setupWorkerTimeout(worker, workerUrl, reject) {
|
|
865
|
+
return window.setTimeout(() => {
|
|
866
|
+
worker.terminate();
|
|
867
|
+
URL.revokeObjectURL(workerUrl);
|
|
868
|
+
reject(
|
|
869
|
+
new Error(`Code execution timeout after ${this.config.timeout}ms`)
|
|
870
|
+
);
|
|
871
|
+
}, this.config.timeout);
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* 设置 Worker 消息处理器
|
|
875
|
+
*/
|
|
876
|
+
setupWorkerHandlers(worker, workerUrl, timeoutId, resolve, reject) {
|
|
877
|
+
worker.onmessage = (e) => {
|
|
878
|
+
const { type, data } = e.data;
|
|
879
|
+
if (type === "result") {
|
|
880
|
+
this.cleanupWorker(worker, workerUrl, timeoutId);
|
|
881
|
+
resolve(data);
|
|
882
|
+
return;
|
|
867
883
|
}
|
|
868
|
-
|
|
884
|
+
if (type === "error") {
|
|
885
|
+
this.cleanupWorker(worker, workerUrl, timeoutId);
|
|
886
|
+
reject(new Error(data.message));
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
this.handleConsoleMessage(type, data);
|
|
890
|
+
};
|
|
891
|
+
worker.onerror = (error) => {
|
|
892
|
+
this.cleanupWorker(worker, workerUrl, timeoutId);
|
|
893
|
+
reject(new Error(`Worker error: ${error.message}`));
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* 处理控制台消息
|
|
898
|
+
*/
|
|
899
|
+
handleConsoleMessage(type, data) {
|
|
900
|
+
if (!this.config.allowConsole)
|
|
901
|
+
return;
|
|
902
|
+
const consoleTypes = ["log", "warn", "error", "info", "debug"];
|
|
903
|
+
if (!consoleTypes.includes(type))
|
|
904
|
+
return;
|
|
905
|
+
const consoleMethod = console[type];
|
|
906
|
+
if (typeof consoleMethod === "function") {
|
|
907
|
+
consoleMethod("[Sandbox]", ...data);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* 清理 Worker 资源
|
|
912
|
+
*/
|
|
913
|
+
cleanupWorker(worker, workerUrl, timeoutId) {
|
|
914
|
+
clearTimeout(timeoutId);
|
|
915
|
+
worker.terminate();
|
|
916
|
+
URL.revokeObjectURL(workerUrl);
|
|
869
917
|
}
|
|
870
918
|
/**
|
|
871
919
|
* 执行代码的核心方法(同步版本)
|