js执行沙箱
创建一个顶层对象(proxy),作为子应用执行js代码时的顶层对象; 隔离不同子应用执行的js代码(js运行环境隔离)
ProxySandbox 代理沙箱
非IE默认使用此沙箱。
ProxySandbox
会返回一个代理到window对象的Proxy提供给子应用使用
- 在qiankun中,proxy对象会被在eval+with作为全局对象使用
js
// js 代理沙箱 基本实现
class ProxySandbox {
constructor() {
const rawWindow = window
const proxyWindow = {}
this.proxy = new Proxy(proxyWindow, {
get(target, key) { // target为第一个参数(代理对象proxyWindow)
return target[key] || window[key]
},
set(target, key, value) {
target[key] = value
return true
}
})
}
}
const ProxySandbox1 = new ProxySandbox()
const ProxySandbox2 = new ProxySandbox()
window.a = 1;
// 沙箱1
((window) => {
window.a = 2
})(ProxySandbox1.proxy);
// 沙箱2
((window) => {
window.a = 3
})(ProxySandbox1.proxy)
// 代理沙箱,互不影响window
console.log(window.a) // 1
SnapshotSandbox 快照沙箱(单例)
不支持Proxy语法则使用此沙箱。
- 基本思路: 把window对象拷贝给一个新对象缓存下来(快照一份),在退出的时候比对下原快照,然后把修改过的属性通过一个 modifyPropsMap 变量存起来,然后通过快照还原window
WARNING
快照沙箱不支持多实例(多个子应用)同时运行,window对象快照会出问题.
js
// js 快照沙箱 基本实现
class SnapshotSandbox {
constructor() {
this.proxy = window
this.modifyPropsMap = {} // 记录被修改的属性
// this.active()
}
// 激活沙箱
active() {
this.windowSnapshot = {} // 用于存放激活时window的快照【每次激活需要清空一次, 否则可能遗留上次多余的属性】
for (const key in window) {
if (window.hasOwnProperty(key)) {
this.windowSnapshot[key] = window[key] // 把window上的属性快照一份
}
}
// 激活时如果发现原来有被更改过的属性,则重新赋值回来
for (const key in this.modifyPropsMap) {
window[key] = this.modifyPropsMap[key]
}
}
// 沙箱失活(切换沙箱)
inactive() {
for (const key in window) {
if (window.hasOwnProperty(key)) {
if (window[key] !== this.windowSnapshot[key]) { // 如果window的某项属性不等于原来快照的属性
this.modifyPropsMap[key] = window[key] // 则保存被更改过的属性
window[key] = this.windowSnapshot[key] // 还原window激活时的属性
}
}
}
}
}
// 1号沙箱
const Sandbox1 = new SnapshotSandbox(); // 这个分号不能少,否则自调用函数(IIFE)报语法错误
Sandbox1.active() // 激活, 快照window属性
window.a = 1 // 新增属性
console.log(window.a) // 1
Sandbox1.inactive() // 失活, 还原window
console.log(window.a) // undefined
Sandbox1.active() // 再激活试试
console.log(window.a) // 1
Sandbox1.inactive() // 失活, 还原window,尝试使用2号沙箱
LegacySandbox 代理沙箱(单例|已弃用)
未深入探究