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