️ use weakmap to instead symbol (#1002)

This commit is contained in:
Kuitos 2020-10-15 20:57:51 +08:00 committed by GitHub
parent 157cba7a44
commit 8ede338a52
4 changed files with 21 additions and 24 deletions

View File

@ -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();
});
});

View File

@ -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.consolewindow.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;
}

View File

@ -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);
}
}
}

View File

@ -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;
}