snapshotSandbox
标签: 核心
# 目录
# SnapshotSandbox
快照沙箱较为简单,这种基于快照机制的沙箱有很大的局限性就是不能同时多个沙箱同时打快照,不然就会混乱,因为快照是直接基于 window 的。代码如下:
function iter(obj: typeof window, callbackFn: (prop: any) => void) {
// eslint-disable-next-line guard-for-in, no-restricted-syntax
for (const prop in obj) {
// patch for clearInterval for compatible reason, see #1490
if (obj.hasOwnProperty(prop) || prop === 'clearInterval') {
callbackFn(prop);
}
}
}
/**
* 基于 diff 方式实现的沙箱,用于不支持 Proxy 的低版本浏览器
*/
export default class SnapshotSandbox implements SandBox {
proxy: WindowProxy;
name: string;
type: SandBoxType;
sandboxRunning = true;
private windowSnapshot!: Window;
private modifyPropsMap: Record<any, any> = {};
constructor(name: string) {
this.name = name;
// 基于快照的实现,直接使用 window
this.proxy = window;
this.type = SandBoxType.Snapshot;
}
active() {
// 记录当前快照
this.windowSnapshot = {} as Window;
// 将 window 上的属性克隆到 windowSnapshot
iter(window, (prop) => {
this.windowSnapshot[prop] = window[prop];
});
// 恢复之前的变更
Object.keys(this.modifyPropsMap).forEach((p: any) => {
window[p] = this.modifyPropsMap[p];
});
this.sandboxRunning = true;
}
inactive() {
// 先清空 modifyPropsMap,理论上在 active 时已经被消费
this.modifyPropsMap = {};
// 如果 window 上的属性和快照上的属性不一致,说明在沙箱中有修改,在 modifyPropsMap 保存这个宝盖以便在重新启动沙箱时恢复,同时将 window 重置为快照的状态
iter(window, (prop) => {
if (window[prop] !== this.windowSnapshot[prop]) {
// 记录变更,恢复环境
this.modifyPropsMap[prop] = window[prop];
window[prop] = this.windowSnapshot[prop];
}
});
this.sandboxRunning = false;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 快照沙箱的核心功能是什么?
快照沙箱有两个主要的任务,一是关闭沙箱时将 window 从快照恢复,二是重新开启沙箱时从缓存恢复上次的沙箱状态。
- 关闭沙箱时将 window 从快照恢复
- 重新开启沙箱时从缓存恢复上次的沙箱状态
# 快照沙箱如何隔离 JS?
快照沙箱在关闭时会将 window 与开启沙箱时的快照进行 diff,并且恢复到快照状态下的 window。
# 优点
快照沙箱有如下优点:
- 原理简单。
- 兼容性很好,几乎所有浏览器都支持。
# 缺点
快照沙箱有如下缺点:
- 不支持多应用实例。一个页面只能有一个沙箱实例。
- 在 active 和 inactive 中都需要迭代大量属性,耗费性能。
- 尽管沙箱关闭时会清理 window,但是在沙箱开启时,主应用和微应用共用一个 window,容易造成 js 混乱。
编辑 (opens new window)
上次更新: 2022/09/06, 14:25:16