From 6732f8b4b01dc12f97f29092cd1f6ff9e79d8506 Mon Sep 17 00:00:00 2001 From: Kuitos Date: Mon, 27 Feb 2023 22:48:40 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20speedy=20mode=20sandbox=20should?= =?UTF-8?q?=20compatible=20with=20element-ui=20popper=20(#2415)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dynamicAppend/forStrictSandbox.ts | 59 +++++++++++++++---- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts b/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts index 1208f01..208f55b 100644 --- a/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts +++ b/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts @@ -29,8 +29,12 @@ const proxyAttachContainerConfigMap: WeakMap = nativeGlobal.__proxyAttachContainerConfigMap__; const elementAttachContainerConfigMap = new WeakMap(); - const docCreatePatchedMap = new WeakMap(); +const mutationObserverPatchedMap = new WeakMap< + typeof MutationObserver.prototype.observe, + typeof MutationObserver.prototype.observe +>(); +const parentNodePatchedMap = new WeakMap(); function patchDocument(cfg: { sandbox: SandBox; speedy: boolean }) { const { sandbox, speedy } = cfg; @@ -74,17 +78,50 @@ function patchDocument(cfg: { sandbox: SandBox; speedy: boolean }) { // patch MutationObserver.prototype.observe to avoid type error // https://github.com/umijs/qiankun/issues/2406 const nativeMutationObserverObserveFn = MutationObserver.prototype.observe; - MutationObserver.prototype.observe = function observe( - this: MutationObserver, - target: Node, - options: MutationObserverInit, - ) { - const realTarget = target instanceof Document ? nativeDocument : target; - return nativeMutationObserverObserveFn.call(this, realTarget, options); - }; + if (!mutationObserverPatchedMap.has(nativeMutationObserverObserveFn)) { + const observe = function observe(this: MutationObserver, target: Node, options: MutationObserverInit) { + const realTarget = target instanceof Document ? nativeDocument : target; + return nativeMutationObserverObserveFn.call(this, realTarget, options); + }; + + MutationObserver.prototype.observe = observe; + mutationObserverPatchedMap.set(nativeMutationObserverObserveFn, observe); + } + + // patch parentNode getter to avoid document === html.parentNode + // https://github.com/umijs/qiankun/issues/2408#issuecomment-1446229105 + const parentNodeDescriptor = Object.getOwnPropertyDescriptor(Node.prototype, 'parentNode'); + if (parentNodeDescriptor && !parentNodePatchedMap.has(parentNodeDescriptor)) { + const { get: parentNodeGetter, configurable } = parentNodeDescriptor; + if (parentNodeGetter && configurable) { + const patchedParentNodeDescriptor = { + ...parentNodeDescriptor, + get(this: Node) { + const parentNode = parentNodeGetter.call(this); + if (parentNode instanceof Document) { + const proxy = getCurrentRunningApp()?.window; + if (proxy) { + return proxy.document; + } + } + + return parentNode; + }, + }; + Object.defineProperty(Node.prototype, 'parentNode', patchedParentNodeDescriptor); + + parentNodePatchedMap.set(parentNodeDescriptor, patchedParentNodeDescriptor); + } + } return () => { MutationObserver.prototype.observe = nativeMutationObserverObserveFn; + mutationObserverPatchedMap.delete(nativeMutationObserverObserveFn); + + if (parentNodeDescriptor) { + Object.defineProperty(Node.prototype, 'parentNode', parentNodeDescriptor); + parentNodePatchedMap.delete(parentNodeDescriptor); + } }; } @@ -150,7 +187,7 @@ export function patchStrictSandbox( // all dynamic style sheets are stored in proxy container const { dynamicStyleSheetElements } = containerConfig; - const unpatchDocumentCreate = patchDocument({ sandbox, speedy: speedySandbox }); + const unpatchDocument = patchDocument({ sandbox, speedy: speedySandbox }); const unpatchDynamicAppendPrototypeFunctions = patchHTMLDynamicAppendPrototypeFunctions( (element) => elementAttachContainerConfigMap.has(element), @@ -167,7 +204,7 @@ export function patchStrictSandbox( // release the overwritten prototype after all the micro apps unmounted if (isAllAppsUnmounted()) { unpatchDynamicAppendPrototypeFunctions(); - unpatchDocumentCreate(); + unpatchDocument(); } recordStyledComponentsCSSRules(dynamicStyleSheetElements);