From 009419f19707b26437c510ad59d1cb57a8b861b5 Mon Sep 17 00:00:00 2001 From: Kuitos Date: Sun, 6 Jun 2021 21:42:49 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20optimize=20current=20proxy=20set?= =?UTF-8?q?ting=20logic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/sandbox/__tests__/proxySandbox.test.ts | 19 ++++++++++++++++++- src/sandbox/common.ts | 2 +- src/sandbox/proxySandbox.ts | 11 ++++++----- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/sandbox/__tests__/proxySandbox.test.ts b/src/sandbox/__tests__/proxySandbox.test.ts index fb0242b9c..2e243b9cf 100644 --- a/src/sandbox/__tests__/proxySandbox.test.ts +++ b/src/sandbox/__tests__/proxySandbox.test.ts @@ -123,7 +123,11 @@ test('hasOwnProperty should works well', () => { test('descriptor of non-configurable and non-enumerable property existed in raw window should be the same after modified in sandbox', () => { Object.defineProperty(window, 'nonConfigurableProp', { configurable: false, writable: true }); // eslint-disable-next-line getter-return - Object.defineProperty(window, 'nonConfigurablePropWithAccessor', { configurable: false, get() {}, set() {} }); + Object.defineProperty(window, 'nonConfigurablePropWithAccessor', { + configurable: false, + get() {}, + set() {}, + }); Object.defineProperty(window, 'enumerableProp', { enumerable: true, writable: true }); Object.defineProperty(window, 'nonEnumerableProp', { enumerable: false, writable: true }); @@ -297,6 +301,7 @@ test('the prototype should be kept while we create a function with prototype on const proxy = new ProxySandbox('new-function').proxy as any; function test() {} + proxy.fn = test; expect(proxy.fn === test).toBeFalsy(); expect(proxy.fn.prototype).toBe(test.prototype); @@ -347,3 +352,15 @@ it('should return true while [[GetPrototypeOf]] invoked by proxy object', () => expect(Reflect.getPrototypeOf(proxy)).toBe(Reflect.getPrototypeOf(window)); expect(Reflect.getPrototypeOf(proxy)).toBe(Object.getPrototypeOf(window)); }); + +it('should get current running sandbox proxy correctly', async () => { + const { proxy } = new ProxySandbox('running'); + + await Promise.resolve().then(() => { + expect(getCurrentRunningSandboxProxy()).toBeNull(); + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const unused = proxy.accessing; + expect(getCurrentRunningSandboxProxy()).toBe(proxy); + }); +}); diff --git a/src/sandbox/common.ts b/src/sandbox/common.ts index 4e8633ba4..4c5416cd2 100644 --- a/src/sandbox/common.ts +++ b/src/sandbox/common.ts @@ -5,7 +5,7 @@ import { isBoundedFunction, isCallable, isConstructable } from '../utils'; -let currentRunningSandboxProxy: WindowProxy | null; +let currentRunningSandboxProxy: WindowProxy | null = null; export function getCurrentRunningSandboxProxy() { return currentRunningSandboxProxy; } diff --git a/src/sandbox/proxySandbox.ts b/src/sandbox/proxySandbox.ts index c46fa7fba..6b679e06f 100644 --- a/src/sandbox/proxySandbox.ts +++ b/src/sandbox/proxySandbox.ts @@ -215,6 +215,12 @@ export default class ProxySandbox implements SandBox { }, get(target: FakeWindow, p: PropertyKey): any { + setCurrentRunningSandboxProxy(proxy); + // FIXME if you have any other good ideas + // remove the mark in next tick, thus we can identify whether it in micro app or not + // this approach is just a workaround, it could not cover all complex cases, such as the micro app runs in the same task context with master in some case + nextTick(() => setCurrentRunningSandboxProxy(null)); + if (p === Symbol.unscopables) return unscopables; // avoid who using window.window or window.self to escape the sandbox environment to touch the really window @@ -247,11 +253,6 @@ export default class ProxySandbox implements SandBox { // mark the symbol to document while accessing as document.createElement could know is invoked by which sandbox for dynamic append patcher if (p === 'document' || p === 'eval') { - setCurrentRunningSandboxProxy(proxy); - // FIXME if you have any other good ideas - // remove the mark in next tick, thus we can identify whether it in micro app or not - // this approach is just a workaround, it could not cover all complex cases, such as the micro app runs in the same task context with master in some case - nextTick(() => setCurrentRunningSandboxProxy(null)); switch (p) { case 'document': return document;