⚡️ use weakmap to instead symbol (#1002)
This commit is contained in:
parent
157cba7a44
commit
8ede338a52
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
import { isBoundedFunction } from '../../utils';
|
||||
import { attachDocProxySymbol } from '../common';
|
||||
import { documentAttachProxyMap } from '../common';
|
||||
import ProxySandbox from '../proxySandbox';
|
||||
|
||||
beforeAll(() => {
|
||||
|
|
@ -206,9 +206,9 @@ test('document accessing should modify the attachDocProxySymbol value every time
|
|||
const proxy2 = new ProxySandbox('doc-access-test2').proxy;
|
||||
|
||||
const d1 = proxy1.document;
|
||||
expect(d1[attachDocProxySymbol]).toBe(proxy1);
|
||||
expect(documentAttachProxyMap.get(d1)).toBe(proxy1);
|
||||
const d2 = proxy2.document;
|
||||
expect(d2[attachDocProxySymbol]).toBe(proxy2);
|
||||
expect(documentAttachProxyMap.get(d2)).toBe(proxy2);
|
||||
|
||||
expect(d1).toBe(d2);
|
||||
expect(d1).toBe(document);
|
||||
|
|
@ -217,10 +217,10 @@ test('document accessing should modify the attachDocProxySymbol value every time
|
|||
test('document attachDocProxySymbol mark should be remove before next tasl', done => {
|
||||
const { proxy } = new ProxySandbox('doc-symbol');
|
||||
const d1 = proxy.document;
|
||||
expect(d1[attachDocProxySymbol]).toBe(proxy);
|
||||
expect(documentAttachProxyMap.get(d1)).toBe(proxy);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(d1[attachDocProxySymbol]).toBeUndefined();
|
||||
expect(documentAttachProxyMap.get(d1)).toBeUndefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,24 +5,18 @@
|
|||
|
||||
import { isBoundedFunction, isCallable, isConstructable } from '../utils';
|
||||
|
||||
export const attachDocProxySymbol = Symbol('attach-proxy-container');
|
||||
|
||||
declare global {
|
||||
interface Document {
|
||||
[attachDocProxySymbol]: WindowProxy;
|
||||
}
|
||||
}
|
||||
|
||||
const boundValueSymbol = Symbol('bound value');
|
||||
export const documentAttachProxyMap = new WeakMap<HTMLDocument, WindowProxy>();
|
||||
|
||||
const functionBoundedValueMap = new WeakMap<Function, Function>();
|
||||
export function getTargetValue(target: any, value: any): any {
|
||||
/*
|
||||
仅绑定 isCallable && !isBoundedFunction && !isConstructable 的函数对象,如 window.console、window.atob 这类。目前没有完美的检测方式,这里通过 prototype 中是否还有可枚举的拓展方法的方式来判断
|
||||
@warning 这里不要随意替换成别的判断方式,因为可能触发一些 edge case(比如在 lodash.isFunction 在 iframe 上下文中可能由于调用了 top window 对象触发的安全异常)
|
||||
*/
|
||||
if (isCallable(value) && !isBoundedFunction(value) && !isConstructable(value)) {
|
||||
if (value[boundValueSymbol]) {
|
||||
return value[boundValueSymbol];
|
||||
const cachedBoundValue = functionBoundedValueMap.get(value);
|
||||
if (cachedBoundValue) {
|
||||
return cachedBoundValue;
|
||||
}
|
||||
|
||||
const boundValue = value.bind(target);
|
||||
|
|
@ -35,7 +29,7 @@ export function getTargetValue(target: any, value: any): any {
|
|||
|
||||
// copy prototype, for performance reason, we use in operator to check rather than hasOwnProperty
|
||||
if ('prototype' in value) boundValue.prototype = value.prototype;
|
||||
Object.defineProperty(value, boundValueSymbol, { enumerable: false, value: boundValue });
|
||||
functionBoundedValueMap.set(value, boundValue);
|
||||
return boundValue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
import { Freer } from '../../../interfaces';
|
||||
import { attachDocProxySymbol } from '../../common';
|
||||
import { documentAttachProxyMap } from '../../common';
|
||||
import {
|
||||
ContainerConfig,
|
||||
isHijackingTag,
|
||||
|
|
@ -27,9 +27,12 @@ function patchDocumentCreateElement() {
|
|||
): HTMLElement {
|
||||
const element = rawDocumentCreateElement.call(this, tagName, options);
|
||||
if (isHijackingTag(tagName)) {
|
||||
const proxyContainerConfig = proxyAttachContainerConfigMap.get(this[attachDocProxySymbol]);
|
||||
if (proxyContainerConfig) {
|
||||
elementAttachContainerConfigMap.set(element, proxyContainerConfig);
|
||||
const attachProxy = documentAttachProxyMap.get(this);
|
||||
if (attachProxy) {
|
||||
const proxyContainerConfig = proxyAttachContainerConfigMap.get(attachProxy);
|
||||
if (proxyContainerConfig) {
|
||||
elementAttachContainerConfigMap.set(element, proxyContainerConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
import { SandBox, SandBoxType } from '../interfaces';
|
||||
import { nextTick } from '../utils';
|
||||
import { attachDocProxySymbol, getTargetValue } from './common';
|
||||
import { documentAttachProxyMap, getTargetValue } from './common';
|
||||
|
||||
/**
|
||||
* fastest(at most time) unique array method
|
||||
|
|
@ -224,11 +224,11 @@ 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') {
|
||||
document[attachDocProxySymbol] = proxy;
|
||||
documentAttachProxyMap.set(document, proxy);
|
||||
// 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(() => delete document[attachDocProxySymbol]);
|
||||
nextTick(() => documentAttachProxyMap.delete(document));
|
||||
return document;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user