🐛 fix the exception while removing a dynamic appending script in a micro app (#975)

* 🐛 fix the exception while removing a dynamic appending script in a micro app

* ️ use weakmap instead
This commit is contained in:
Kuitos 2020-10-09 17:56:41 +08:00 committed by GitHub
parent bde70ca293
commit 0a0bdaa9be

View File

@ -82,6 +82,7 @@ function getOverwrittenAppendChildOrInsertBefore(opts: {
rawDOMAppendOrInsertBefore: <T extends Node>(newChild: T, refChild?: Node | null) => T; rawDOMAppendOrInsertBefore: <T extends Node>(newChild: T, refChild?: Node | null) => T;
scopedCSS: boolean; scopedCSS: boolean;
excludeAssetFilter?: CallableFunction; excludeAssetFilter?: CallableFunction;
elementAttachmentMap: WeakMap<HTMLElement, Node>;
}) { }) {
return function appendChildOrInsertBefore<T extends Node>( return function appendChildOrInsertBefore<T extends Node>(
this: HTMLHeadElement | HTMLBodyElement, this: HTMLHeadElement | HTMLBodyElement,
@ -191,6 +192,7 @@ function getOverwrittenAppendChildOrInsertBefore(opts: {
}); });
const dynamicScriptCommentElement = document.createComment(`dynamic script ${src} replaced by qiankun`); const dynamicScriptCommentElement = document.createComment(`dynamic script ${src} replaced by qiankun`);
opts.elementAttachmentMap.set(element, dynamicScriptCommentElement);
return rawDOMAppendOrInsertBefore.call(mountDOM, dynamicScriptCommentElement, referenceNode); return rawDOMAppendOrInsertBefore.call(mountDOM, dynamicScriptCommentElement, referenceNode);
} }
@ -200,6 +202,7 @@ function getOverwrittenAppendChildOrInsertBefore(opts: {
error: element.onerror, error: element.onerror,
}); });
const dynamicInlineScriptCommentElement = document.createComment('dynamic inline script replaced by qiankun'); const dynamicInlineScriptCommentElement = document.createComment('dynamic inline script replaced by qiankun');
opts.elementAttachmentMap.set(element, dynamicInlineScriptCommentElement);
return rawDOMAppendOrInsertBefore.call(mountDOM, dynamicInlineScriptCommentElement, referenceNode); return rawDOMAppendOrInsertBefore.call(mountDOM, dynamicInlineScriptCommentElement, referenceNode);
} }
@ -215,6 +218,7 @@ function getOverwrittenAppendChildOrInsertBefore(opts: {
function getNewRemoveChild(opts: { function getNewRemoveChild(opts: {
appWrapperGetter: CallableFunction; appWrapperGetter: CallableFunction;
headOrBodyRemoveChild: typeof HTMLElement.prototype.removeChild; headOrBodyRemoveChild: typeof HTMLElement.prototype.removeChild;
elementAttachmentMap: WeakMap<HTMLElement, Node>;
}) { }) {
return function removeChild<T extends Node>(this: HTMLHeadElement | HTMLBodyElement, child: T) { return function removeChild<T extends Node>(this: HTMLHeadElement | HTMLBodyElement, child: T) {
const { headOrBodyRemoveChild } = opts; const { headOrBodyRemoveChild } = opts;
@ -231,8 +235,9 @@ function getNewRemoveChild(opts: {
// container may had been removed while app unmounting if the removeChild action was async // container may had been removed while app unmounting if the removeChild action was async
const container = appWrapperGetter(); const container = appWrapperGetter();
if (container.contains(child)) { const attachedElement = opts.elementAttachmentMap.get(child as any) || child;
return rawRemoveChild.call(container, child) as T; if (container.contains(attachedElement)) {
return rawRemoveChild.call(container, attachedElement) as T;
} }
} }
} catch (e) { } catch (e) {
@ -252,6 +257,8 @@ function patchHTMLDynamicAppendPrototypeFunctions(
dynamicStyleSheetElements: HTMLStyleElement[], dynamicStyleSheetElements: HTMLStyleElement[],
excludeAssetFilter?: CallableFunction, excludeAssetFilter?: CallableFunction,
) { ) {
const elementAttachmentMap = new WeakMap();
// Just overwrite it while it have not been overwrite // Just overwrite it while it have not been overwrite
if ( if (
HTMLHeadElement.prototype.appendChild === rawHeadAppendChild && HTMLHeadElement.prototype.appendChild === rawHeadAppendChild &&
@ -267,6 +274,7 @@ function patchHTMLDynamicAppendPrototypeFunctions(
dynamicStyleSheetElements, dynamicStyleSheetElements,
scopedCSS, scopedCSS,
excludeAssetFilter, excludeAssetFilter,
elementAttachmentMap,
}) as typeof rawHeadAppendChild; }) as typeof rawHeadAppendChild;
HTMLBodyElement.prototype.appendChild = getOverwrittenAppendChildOrInsertBefore({ HTMLBodyElement.prototype.appendChild = getOverwrittenAppendChildOrInsertBefore({
rawDOMAppendOrInsertBefore: rawBodyAppendChild, rawDOMAppendOrInsertBefore: rawBodyAppendChild,
@ -277,6 +285,7 @@ function patchHTMLDynamicAppendPrototypeFunctions(
dynamicStyleSheetElements, dynamicStyleSheetElements,
scopedCSS, scopedCSS,
excludeAssetFilter, excludeAssetFilter,
elementAttachmentMap,
}) as typeof rawBodyAppendChild; }) as typeof rawBodyAppendChild;
HTMLHeadElement.prototype.insertBefore = getOverwrittenAppendChildOrInsertBefore({ HTMLHeadElement.prototype.insertBefore = getOverwrittenAppendChildOrInsertBefore({
@ -288,6 +297,7 @@ function patchHTMLDynamicAppendPrototypeFunctions(
dynamicStyleSheetElements, dynamicStyleSheetElements,
scopedCSS, scopedCSS,
excludeAssetFilter, excludeAssetFilter,
elementAttachmentMap,
}) as typeof rawHeadInsertBefore; }) as typeof rawHeadInsertBefore;
} }
@ -299,10 +309,12 @@ function patchHTMLDynamicAppendPrototypeFunctions(
HTMLHeadElement.prototype.removeChild = getNewRemoveChild({ HTMLHeadElement.prototype.removeChild = getNewRemoveChild({
appWrapperGetter, appWrapperGetter,
headOrBodyRemoveChild: rawHeadRemoveChild, headOrBodyRemoveChild: rawHeadRemoveChild,
elementAttachmentMap,
}); });
HTMLBodyElement.prototype.removeChild = getNewRemoveChild({ HTMLBodyElement.prototype.removeChild = getNewRemoveChild({
appWrapperGetter, appWrapperGetter,
headOrBodyRemoveChild: rawBodyRemoveChild, headOrBodyRemoveChild: rawBodyRemoveChild,
elementAttachmentMap,
}); });
} }