🐛 prevent sandbox from deleting an existed whitelisted global variable, should restore it instead (#2287)

This commit is contained in:
李凤宝(Ted) 2022-10-05 16:22:29 +08:00 committed by GitHub
parent e5a175caa4
commit c14ae3f083
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 3 deletions

View File

@ -409,6 +409,36 @@ it('native window function calling should always be bound with window', () => {
expect(proxy.nativeWindowFunction()).toBe('success'); expect(proxy.nativeWindowFunction()).toBe('success');
}); });
it('should restore window properties (primitive values) that in whitelisted variables', () => {
const original = {
iframeReady: () => {},
};
window.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__ = original;
const sandbox = new ProxySandbox('whitelist-variables');
const { proxy } = sandbox;
sandbox.active();
proxy.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__ = undefined;
sandbox.inactive();
proxy.expect(window.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__).toBe(original);
});
it('should restore window properties (object descriptors) that in whitelisted variables', () => {
const original = {
iframeReady: () => {},
};
Object.defineProperty(window, '__REACT_ERROR_OVERLAY_GLOBAL_HOOK__', {
value: original,
});
const sandbox = new ProxySandbox('whitelist-variables');
const { proxy } = sandbox;
sandbox.active();
proxy.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__ = {};
sandbox.inactive();
proxy.expect(window.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__).toBe(original);
});
describe('should work with nest sandbox', () => { describe('should work with nest sandbox', () => {
it('specified dom api should bound with native window', () => { it('specified dom api should bound with native window', () => {
const { proxy: sandboxProxy } = new ProxySandbox('sandbox'); const { proxy: sandboxProxy } = new ProxySandbox('sandbox');

View File

@ -146,9 +146,9 @@ export default class ProxySandbox implements SandBox {
if (--activeSandboxCount === 0) { if (--activeSandboxCount === 0) {
variableWhiteList.forEach((p) => { variableWhiteList.forEach((p) => {
if (this.proxy.hasOwnProperty(p)) { const descriptor = this.globalWhiteList[p];
// @ts-ignore if (descriptor && descriptor.writable) {
delete this.globalContext[p]; Object.defineProperty(this.globalContext, p, descriptor);
} }
}); });
} }
@ -157,10 +157,16 @@ export default class ProxySandbox implements SandBox {
} }
globalContext: typeof window; globalContext: typeof window;
/** the whitelisted original global variables */
globalWhiteList: Record<PropertyKey, PropertyDescriptor | undefined>;
constructor(name: string, globalContext = window) { constructor(name: string, globalContext = window) {
this.name = name; this.name = name;
this.globalContext = globalContext; this.globalContext = globalContext;
this.globalWhiteList = variableWhiteList.reduce((acc, key) => {
acc[key] = Object.getOwnPropertyDescriptor(globalContext, key);
return acc;
}, {} as ProxySandbox['globalWhiteList']);
this.type = SandBoxType.Proxy; this.type = SandBoxType.Proxy;
const { updatedValueSet } = this; const { updatedValueSet } = this;