✨ add internal getCurrentRunningApp api (#1697)
This commit is contained in:
parent
b789e6c529
commit
ad7feadd29
|
|
@ -396,7 +396,7 @@ A criterion for judging whether the business is closely related: <strong>Look at
|
|||
|
||||
- Usage
|
||||
|
||||
init global state, and return actions for communication. It is recommended to use in master, and slave get actions through props。
|
||||
init global state, and return actions for communication. It is recommended to use in master, and slave get actions through props.
|
||||
|
||||
- Return
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
import { isBoundedFunction } from '../../utils';
|
||||
import { getCurrentRunningSandboxProxy } from '../common';
|
||||
import { getCurrentRunningApp } from '../common';
|
||||
import ProxySandbox from '../proxySandbox';
|
||||
|
||||
declare global {
|
||||
|
|
@ -234,17 +234,21 @@ test('document and eval accessing should modify the attachDocProxySymbol value e
|
|||
const proxy4 = new ProxySandbox('eval-access-test2').proxy;
|
||||
|
||||
const d1 = proxy1.document;
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy1);
|
||||
expect(getCurrentRunningApp()?.window).toBe(proxy1);
|
||||
expect(getCurrentRunningApp()?.name).toBe('doc-access-test1');
|
||||
const d2 = proxy2.document;
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy2);
|
||||
expect(getCurrentRunningApp()?.window).toBe(proxy2);
|
||||
expect(getCurrentRunningApp()?.name).toBe('doc-access-test2');
|
||||
|
||||
expect(d1).toBe(d2);
|
||||
expect(d1).toBe(document);
|
||||
|
||||
const eval1 = proxy3.eval;
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy3);
|
||||
expect(getCurrentRunningApp()?.window).toBe(proxy3);
|
||||
expect(getCurrentRunningApp()?.name).toBe('eval-access-test1');
|
||||
const eval2 = proxy4.eval;
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy4);
|
||||
expect(getCurrentRunningApp()?.window).toBe(proxy4);
|
||||
expect(getCurrentRunningApp()?.name).toBe('eval-access-test2');
|
||||
|
||||
expect(eval1).toBe(eval2);
|
||||
// eslint-disable-next-line no-eval
|
||||
|
|
@ -257,10 +261,11 @@ test('document attachDocProxySymbol mark should be remove before next task', (do
|
|||
// @ts-ignore
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const d1 = proxy.document;
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy);
|
||||
expect(getCurrentRunningApp()?.window).toBe(proxy);
|
||||
expect(getCurrentRunningApp()?.name).toBe('doc-symbol');
|
||||
|
||||
setTimeout(() => {
|
||||
expect(getCurrentRunningSandboxProxy()).toBeNull();
|
||||
expect(getCurrentRunningApp()).toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
@ -357,11 +362,12 @@ it('should get current running sandbox proxy correctly', async () => {
|
|||
const { proxy } = new ProxySandbox('running');
|
||||
|
||||
await Promise.resolve().then(() => {
|
||||
expect(getCurrentRunningSandboxProxy()).toBeNull();
|
||||
expect(getCurrentRunningApp()).toBeNull();
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const unused = proxy.accessing;
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy);
|
||||
expect(getCurrentRunningApp()?.window).toBe(proxy);
|
||||
expect(getCurrentRunningApp()?.name).toBe('running');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -7,21 +7,26 @@ import { isBoundedFunction, isCallable, isConstructable } from '../utils';
|
|||
|
||||
declare global {
|
||||
interface Window {
|
||||
__currentRunningSandboxProxy__: WindowProxy | null;
|
||||
__currentRunningAppInSandbox__: { name: string; window: WindowProxy } | null;
|
||||
}
|
||||
}
|
||||
|
||||
// Get native global window with a sandbox disgusted way, thus we could share it between qiankun instances🤪
|
||||
// eslint-disable-next-line no-new-func
|
||||
const nativeGlobal: Window = new Function('return this')();
|
||||
Object.defineProperty(nativeGlobal, '__currentRunningSandboxProxy__', { enumerable: false, writable: true });
|
||||
export function getCurrentRunningSandboxProxy() {
|
||||
return nativeGlobal.__currentRunningSandboxProxy__;
|
||||
Object.defineProperty(nativeGlobal, '__currentRunningAppInSandbox__', { enumerable: false, writable: true });
|
||||
|
||||
/**
|
||||
* get the app that running tasks at current tick
|
||||
* @warning this method only works with proxy sandbox, right now it is for internal use only.
|
||||
*/
|
||||
export function getCurrentRunningApp() {
|
||||
return nativeGlobal.__currentRunningAppInSandbox__;
|
||||
}
|
||||
|
||||
export function setCurrentRunningSandboxProxy(proxy: WindowProxy | null) {
|
||||
// set currentRunningSandboxProxy to global window, as its only use case is for document.createElement from now on, which hijacked by a global way
|
||||
nativeGlobal.__currentRunningSandboxProxy__ = proxy;
|
||||
export function setCurrentRunningApp(instance: { name: string; window: WindowProxy } | null) {
|
||||
// set currentRunningApp and it's proxySandbox to global window, as its only use case is for document.createElement from now on, which hijacked by a global way
|
||||
nativeGlobal.__currentRunningAppInSandbox__ = instance;
|
||||
}
|
||||
|
||||
const functionBoundedValueMap = new WeakMap<CallableFunction, CallableFunction>();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
import type { Freer } from '../../../interfaces';
|
||||
import { getCurrentRunningSandboxProxy } from '../../common';
|
||||
import { getCurrentRunningApp } from '../../common';
|
||||
import type { ContainerConfig } from './common';
|
||||
import {
|
||||
isHijackingTag,
|
||||
|
|
@ -27,7 +27,7 @@ function patchDocumentCreateElement() {
|
|||
): HTMLElement {
|
||||
const element = rawDocumentCreateElement.call(this, tagName, options);
|
||||
if (isHijackingTag(tagName)) {
|
||||
const currentRunningSandboxProxy = getCurrentRunningSandboxProxy();
|
||||
const { window: currentRunningSandboxProxy } = getCurrentRunningApp() || {};
|
||||
if (currentRunningSandboxProxy) {
|
||||
const proxyContainerConfig = proxyAttachContainerConfigMap.get(currentRunningSandboxProxy);
|
||||
if (proxyContainerConfig) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
import type { SandBox } from '../interfaces';
|
||||
import { SandBoxType } from '../interfaces';
|
||||
import { nextTask } from '../utils';
|
||||
import { getTargetValue, setCurrentRunningSandboxProxy } from './common';
|
||||
import { getTargetValue, setCurrentRunningApp } from './common';
|
||||
|
||||
/**
|
||||
* fastest(at most time) unique array method
|
||||
|
|
@ -122,6 +122,16 @@ function createFakeWindow(global: Window) {
|
|||
|
||||
let activeSandboxCount = 0;
|
||||
|
||||
function registerRunningApp(name: string, proxy: Window) {
|
||||
setCurrentRunningApp({ name, window: 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
|
||||
nextTask(() => {
|
||||
setCurrentRunningApp(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于 Proxy 实现的沙箱
|
||||
*/
|
||||
|
|
@ -177,6 +187,7 @@ export default class ProxySandbox implements SandBox {
|
|||
const proxy = new Proxy(fakeWindow, {
|
||||
set: (target: FakeWindow, p: PropertyKey, value: any): boolean => {
|
||||
if (this.sandboxRunning) {
|
||||
registerRunningApp(name, proxy);
|
||||
// We must kept its description while the property existed in rawWindow before
|
||||
if (!target.hasOwnProperty(p) && rawWindow.hasOwnProperty(p)) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(rawWindow, p);
|
||||
|
|
@ -216,13 +227,7 @@ export default class ProxySandbox implements SandBox {
|
|||
|
||||
get(target: FakeWindow, p: PropertyKey): any {
|
||||
if (p === Symbol.unscopables) return unscopables;
|
||||
|
||||
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
|
||||
nextTask(() => setCurrentRunningSandboxProxy(null));
|
||||
|
||||
registerRunningApp(name, proxy);
|
||||
// avoid who using window.window or window.self to escape the sandbox environment to touch the really window
|
||||
// see https://github.com/eligrey/FileSaver.js/blob/master/src/FileSaver.js#L13
|
||||
if (p === 'window' || p === 'self') {
|
||||
|
|
@ -323,6 +328,7 @@ export default class ProxySandbox implements SandBox {
|
|||
},
|
||||
|
||||
deleteProperty(target: FakeWindow, p: string | number | symbol): boolean {
|
||||
registerRunningApp(name, proxy);
|
||||
if (target.hasOwnProperty(p)) {
|
||||
// @ts-ignore
|
||||
delete target[p];
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user