🐛 avoid illegal invocation error while using some dom api in nest sandbox (#1768)
This commit is contained in:
parent
ab64a7047b
commit
df24f02e92
|
|
@ -383,3 +383,30 @@ it('native window function calling should always be bound with window', () => {
|
|||
const { proxy } = new ProxySandbox('mustBeBoundWithWindowReference');
|
||||
expect(proxy.nativeWindowFunction()).toBe('success');
|
||||
});
|
||||
|
||||
describe('should work with nest sandbox', () => {
|
||||
it('specified dom api should bound with native window', () => {
|
||||
const { proxy: sandboxProxy } = new ProxySandbox('sandbox');
|
||||
const { proxy: nestProxy } = new ProxySandbox('dom-api', sandboxProxy as typeof window);
|
||||
|
||||
function mockDomAPI(this: any) {
|
||||
if (this !== window) {
|
||||
throw new TypeError('Illegal invocation!');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nestProxy.mockDomAPIInBlackList = mockDomAPI;
|
||||
// must use a new function to avoid cache
|
||||
nestProxy.mockDomAPINotInBlackList = function fnCp(this: any) {
|
||||
return mockDomAPI.call(this);
|
||||
};
|
||||
|
||||
expect(nestProxy.mockDomAPIInBlackList()).toBeTruthy();
|
||||
|
||||
expect(() => {
|
||||
nestProxy.mockDomAPINotInBlackList();
|
||||
}).toThrowError(/Illegal invocation!/);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
import type { Freer } from '../../../interfaces';
|
||||
import { nativeGlobal } from '../../../utils';
|
||||
import { getCurrentRunningApp } from '../../common';
|
||||
import type { ContainerConfig } from './common';
|
||||
import {
|
||||
|
|
@ -21,8 +22,6 @@ declare global {
|
|||
}
|
||||
|
||||
// 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, '__proxyAttachContainerConfigMap__', { enumerable: false, writable: true });
|
||||
|
||||
// Share proxyAttachContainerConfigMap between multiple qiankun instance, thus they could access the same record
|
||||
|
|
|
|||
|
|
@ -5,9 +5,13 @@
|
|||
*/
|
||||
import type { SandBox } from '../interfaces';
|
||||
import { SandBoxType } from '../interfaces';
|
||||
import { nextTask } from '../utils';
|
||||
import { nativeGlobal, nextTask } from '../utils';
|
||||
import { getTargetValue, setCurrentRunningApp } from './common';
|
||||
|
||||
type SymbolTarget = 'target' | 'globalContext';
|
||||
|
||||
type FakeWindow = Window & Record<PropertyKey, any>;
|
||||
|
||||
/**
|
||||
* fastest(at most time) unique array method
|
||||
* @see https://jsperf.com/array-filter-unique/30
|
||||
|
|
@ -57,9 +61,10 @@ const unscopables = {
|
|||
Float32Array: true,
|
||||
};
|
||||
|
||||
type SymbolTarget = 'target' | 'globalContext';
|
||||
|
||||
type FakeWindow = Window & Record<PropertyKey, any>;
|
||||
const useNativeWindowForBindingsProps = new Map<PropertyKey, boolean>([
|
||||
['fetch', true],
|
||||
['mockDomAPIInBlackList', process.env.NODE_ENV === 'test'],
|
||||
]);
|
||||
|
||||
function createFakeWindow(globalContext: Window) {
|
||||
// map always has the fastest performance in has check scenario
|
||||
|
|
@ -269,13 +274,19 @@ export default class ProxySandbox implements SandBox {
|
|||
return eval;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
const value = propertiesWithGetter.has(p)
|
||||
? (globalContext as any)[p]
|
||||
: p in target
|
||||
? (target as any)[p]
|
||||
: (globalContext as any)[p];
|
||||
return getTargetValue(globalContext, value);
|
||||
/* Some dom api must be bound to native window, otherwise it would cause exception like 'TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation'
|
||||
See this code:
|
||||
const proxy = new Proxy(window, {});
|
||||
const proxyFetch = fetch.bind(proxy);
|
||||
proxyFetch('https://qiankun.com');
|
||||
*/
|
||||
const boundTarget = useNativeWindowForBindingsProps.get(p) ? nativeGlobal : globalContext;
|
||||
return getTargetValue(boundTarget, value);
|
||||
},
|
||||
|
||||
// trap in operator
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ export function getWrapperId(id: string) {
|
|||
return `__qiankun_microapp_wrapper_for_${snakeCase(id)}__`;
|
||||
}
|
||||
|
||||
export const nativeGlobal = new Function('return this')();
|
||||
|
||||
/** 校验子应用导出的 生命周期 对象是否正确 */
|
||||
export function validateExportLifecycle(exports: any) {
|
||||
const { bootstrap, mount, unmount } = exports ?? {};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user