✨ hijack dynamic document appending in evalling code (#1052)
This commit is contained in:
parent
798f3437b9
commit
3fa008be96
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
import { isBoundedFunction } from '../../utils';
|
||||
import { documentAttachProxyMap } from '../common';
|
||||
import { getCurrentRunningSandboxProxy } from '../common';
|
||||
import ProxySandbox from '../proxySandbox';
|
||||
|
||||
beforeAll(() => {
|
||||
|
|
@ -201,26 +201,42 @@ test('hasOwnProperty should always returns same reference', () => {
|
|||
expect(proxy.testA.hasOwnProperty).toBe(proxy.testB.hasOwnProperty);
|
||||
});
|
||||
|
||||
test('document accessing should modify the attachDocProxySymbol value every time', () => {
|
||||
test('document and eval accessing should modify the attachDocProxySymbol value every time', () => {
|
||||
const proxy1 = new ProxySandbox('doc-access-test1').proxy;
|
||||
const proxy2 = new ProxySandbox('doc-access-test2').proxy;
|
||||
const proxy3 = new ProxySandbox('eval-access-test1').proxy;
|
||||
const proxy4 = new ProxySandbox('eval-access-test2').proxy;
|
||||
|
||||
const d1 = proxy1.document;
|
||||
expect(documentAttachProxyMap.get(d1)).toBe(proxy1);
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy1);
|
||||
const d2 = proxy2.document;
|
||||
expect(documentAttachProxyMap.get(d2)).toBe(proxy2);
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy2);
|
||||
|
||||
expect(d1).toBe(d2);
|
||||
expect(d1).toBe(document);
|
||||
|
||||
// @ts-ignore
|
||||
const eval1 = proxy3.eval;
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy3);
|
||||
// @ts-ignore
|
||||
const eval2 = proxy4.eval;
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy4);
|
||||
|
||||
expect(eval1).toBe(eval2);
|
||||
// eslint-disable-next-line no-eval
|
||||
expect(eval1).toBe(eval);
|
||||
});
|
||||
|
||||
test('document attachDocProxySymbol mark should be remove before next tasl', (done) => {
|
||||
test('document attachDocProxySymbol mark should be remove before next task', (done) => {
|
||||
const { proxy } = new ProxySandbox('doc-symbol');
|
||||
// just access
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const d1 = proxy.document;
|
||||
expect(documentAttachProxyMap.get(d1)).toBe(proxy);
|
||||
expect(getCurrentRunningSandboxProxy()).toBe(proxy);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(documentAttachProxyMap.get(d1)).toBeUndefined();
|
||||
expect(getCurrentRunningSandboxProxy()).toBeNull();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,7 +5,14 @@
|
|||
|
||||
import { isBoundedFunction, isCallable, isConstructable } from '../utils';
|
||||
|
||||
export const documentAttachProxyMap = new WeakMap<HTMLDocument, WindowProxy>();
|
||||
let currentRunningSandboxProxy: WindowProxy | null;
|
||||
export function getCurrentRunningSandboxProxy() {
|
||||
return currentRunningSandboxProxy;
|
||||
}
|
||||
|
||||
export function setCurrentRunningSandboxProxy(proxy: WindowProxy | null) {
|
||||
currentRunningSandboxProxy = proxy;
|
||||
}
|
||||
|
||||
const functionBoundedValueMap = new WeakMap<Function, Function>();
|
||||
export function getTargetValue(target: any, value: any): any {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
import { Freer } from '../../../interfaces';
|
||||
import { documentAttachProxyMap } from '../../common';
|
||||
import { getCurrentRunningSandboxProxy } from '../../common';
|
||||
import {
|
||||
ContainerConfig,
|
||||
isHijackingTag,
|
||||
|
|
@ -27,11 +27,9 @@ function patchDocumentCreateElement() {
|
|||
): HTMLElement {
|
||||
const element = rawDocumentCreateElement.call(this, tagName, options);
|
||||
if (isHijackingTag(tagName)) {
|
||||
// 这里使用document来获取比this更加健壮,因为之前set的时候是传入的document:
|
||||
// 因为document不一定是原生的document,这种情况出现在qiankun本身就在另一个沙箱下运行的情况,而那个沙箱可能连document都重写了。
|
||||
const attachProxy = documentAttachProxyMap.get(document);
|
||||
if (attachProxy) {
|
||||
const proxyContainerConfig = proxyAttachContainerConfigMap.get(attachProxy);
|
||||
const currentRunningSandboxProxy = getCurrentRunningSandboxProxy();
|
||||
if (currentRunningSandboxProxy) {
|
||||
const proxyContainerConfig = proxyAttachContainerConfigMap.get(currentRunningSandboxProxy);
|
||||
if (proxyContainerConfig) {
|
||||
elementAttachContainerConfigMap.set(element, proxyContainerConfig);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
import { SandBox, SandBoxType } from '../interfaces';
|
||||
import { nextTick } from '../utils';
|
||||
import { documentAttachProxyMap, getTargetValue } from './common';
|
||||
import { getTargetValue, setCurrentRunningSandboxProxy } from './common';
|
||||
|
||||
/**
|
||||
* fastest(at most time) unique array method
|
||||
|
|
@ -50,7 +50,6 @@ const unscopables = {
|
|||
String: true,
|
||||
Boolean: true,
|
||||
Math: true,
|
||||
eval: true,
|
||||
Number: true,
|
||||
Symbol: true,
|
||||
parseFloat: true,
|
||||
|
|
@ -223,13 +222,20 @@ 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') {
|
||||
documentAttachProxyMap.set(document, proxy);
|
||||
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 the complex scenarios, such as the micro app runs in the same task context with master in som case
|
||||
// fixme if you have any other good ideas
|
||||
nextTick(() => documentAttachProxyMap.delete(document));
|
||||
return document;
|
||||
// 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;
|
||||
case 'eval':
|
||||
// eslint-disable-next-line no-eval
|
||||
return eval;
|
||||
// no default
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-bitwise
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user