✨ loose sandbox support mutaion with defineProperty (#1581)
This commit is contained in:
parent
f00f2ca655
commit
116f40a2cd
27
src/sandbox/legacy/__tests__/sandbox.test.ts
Normal file
27
src/sandbox/legacy/__tests__/sandbox.test.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* @author Kuitos
|
||||||
|
* @since 2021-07-19
|
||||||
|
*/
|
||||||
|
|
||||||
|
import LooseSandbox from '../sandbox';
|
||||||
|
|
||||||
|
describe('loose sandbox', () => {
|
||||||
|
it('should record the mutation from Object.defineProperty', () => {
|
||||||
|
const sandbox = new LooseSandbox('defineProperty');
|
||||||
|
|
||||||
|
const { proxy } = sandbox;
|
||||||
|
|
||||||
|
proxy.prop1 = 123;
|
||||||
|
Object.defineProperty(proxy, 'prop2', { value: 456, configurable: true, writable: true });
|
||||||
|
|
||||||
|
expect(proxy.prop1).toBe(123);
|
||||||
|
expect(window.prop1).toBe(123);
|
||||||
|
expect(proxy.prop2).toBe(456);
|
||||||
|
expect(window.prop2).toBe(456);
|
||||||
|
|
||||||
|
sandbox.inactive();
|
||||||
|
|
||||||
|
expect(window.prop1).toBeUndefined();
|
||||||
|
expect(window.prop2).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -76,21 +76,21 @@ export default class SingularProxySandbox implements SandBox {
|
||||||
const rawWindow = window;
|
const rawWindow = window;
|
||||||
const fakeWindow = Object.create(null) as Window;
|
const fakeWindow = Object.create(null) as Window;
|
||||||
|
|
||||||
const proxy = new Proxy(fakeWindow, {
|
const setTrap = (p: PropertyKey, value: any, originalValue: any, sync2Window = true) => {
|
||||||
set: (_: Window, p: PropertyKey, value: any): boolean => {
|
|
||||||
if (this.sandboxRunning) {
|
if (this.sandboxRunning) {
|
||||||
if (!rawWindow.hasOwnProperty(p)) {
|
if (!rawWindow.hasOwnProperty(p)) {
|
||||||
addedPropsMapInSandbox.set(p, value);
|
addedPropsMapInSandbox.set(p, value);
|
||||||
} else if (!modifiedPropsOriginalValueMapInSandbox.has(p)) {
|
} else if (!modifiedPropsOriginalValueMapInSandbox.has(p)) {
|
||||||
// 如果当前 window 对象存在该属性,且 record map 中未记录过,则记录该属性初始值
|
// 如果当前 window 对象存在该属性,且 record map 中未记录过,则记录该属性初始值
|
||||||
const originalValue = (rawWindow as any)[p];
|
|
||||||
modifiedPropsOriginalValueMapInSandbox.set(p, originalValue);
|
modifiedPropsOriginalValueMapInSandbox.set(p, originalValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentUpdatedPropsValueMap.set(p, value);
|
currentUpdatedPropsValueMap.set(p, value);
|
||||||
|
|
||||||
|
if (sync2Window) {
|
||||||
// 必须重新设置 window 对象保证下次 get 时能拿到已更新的数据
|
// 必须重新设置 window 对象保证下次 get 时能拿到已更新的数据
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
(rawWindow as any)[p] = value;
|
(rawWindow as any)[p] = value;
|
||||||
|
}
|
||||||
|
|
||||||
this.latestSetProp = p;
|
this.latestSetProp = p;
|
||||||
|
|
||||||
|
|
@ -103,6 +103,12 @@ export default class SingularProxySandbox implements SandBox {
|
||||||
|
|
||||||
// 在 strict-mode 下,Proxy 的 handler.set 返回 false 会抛出 TypeError,在沙箱卸载的情况下应该忽略错误
|
// 在 strict-mode 下,Proxy 的 handler.set 返回 false 会抛出 TypeError,在沙箱卸载的情况下应该忽略错误
|
||||||
return true;
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const proxy = new Proxy(fakeWindow, {
|
||||||
|
set: (_: Window, p: PropertyKey, value: any): boolean => {
|
||||||
|
const originalValue = (rawWindow as any)[p];
|
||||||
|
return setTrap(p, value, originalValue, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
get(_: Window, p: PropertyKey): any {
|
get(_: Window, p: PropertyKey): any {
|
||||||
|
|
@ -131,6 +137,15 @@ export default class SingularProxySandbox implements SandBox {
|
||||||
}
|
}
|
||||||
return descriptor;
|
return descriptor;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
defineProperty(_: Window, p: string | symbol, attributes: PropertyDescriptor): boolean {
|
||||||
|
const originalValue = (rawWindow as any)[p];
|
||||||
|
const done = Reflect.defineProperty(rawWindow, p, attributes);
|
||||||
|
const value = (rawWindow as any)[p];
|
||||||
|
setTrap(p, value, originalValue, false);
|
||||||
|
|
||||||
|
return done;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.proxy = proxy;
|
this.proxy = proxy;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user