diff --git a/src/sandbox/__tests__/proxySandbox.test.ts b/src/sandbox/__tests__/proxySandbox.test.ts index 009b468..f2e73b8 100644 --- a/src/sandbox/__tests__/proxySandbox.test.ts +++ b/src/sandbox/__tests__/proxySandbox.test.ts @@ -409,6 +409,36 @@ it('native window function calling should always be bound with window', () => { 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', () => { it('specified dom api should bound with native window', () => { const { proxy: sandboxProxy } = new ProxySandbox('sandbox'); diff --git a/src/sandbox/proxySandbox.ts b/src/sandbox/proxySandbox.ts index 7eca70d..e1295b6 100644 --- a/src/sandbox/proxySandbox.ts +++ b/src/sandbox/proxySandbox.ts @@ -146,9 +146,9 @@ export default class ProxySandbox implements SandBox { if (--activeSandboxCount === 0) { variableWhiteList.forEach((p) => { - if (this.proxy.hasOwnProperty(p)) { - // @ts-ignore - delete this.globalContext[p]; + const descriptor = this.globalWhiteList[p]; + if (descriptor && descriptor.writable) { + Object.defineProperty(this.globalContext, p, descriptor); } }); } @@ -157,10 +157,16 @@ export default class ProxySandbox implements SandBox { } globalContext: typeof window; + /** the whitelisted original global variables */ + globalWhiteList: Record; constructor(name: string, globalContext = window) { this.name = name; this.globalContext = globalContext; + this.globalWhiteList = variableWhiteList.reduce((acc, key) => { + acc[key] = Object.getOwnPropertyDescriptor(globalContext, key); + return acc; + }, {} as ProxySandbox['globalWhiteList']); this.type = SandBoxType.Proxy; const { updatedValueSet } = this;