diff --git a/src/sandbox/patchers/dynamicAppend/common.ts b/src/sandbox/patchers/dynamicAppend/common.ts index 79f2fb9..7a927ac 100644 --- a/src/sandbox/patchers/dynamicAppend/common.ts +++ b/src/sandbox/patchers/dynamicAppend/common.ts @@ -349,24 +349,25 @@ export function patchHTMLDynamicAppendPrototypeFunctions( export function rebuildCSSRules( styleSheetElements: HTMLStyleElement[], - reAppendElement: (stylesheetElement: HTMLStyleElement) => void, + reAppendElement: (stylesheetElement: HTMLStyleElement) => boolean, ) { styleSheetElements.forEach((stylesheetElement) => { // re-append the dynamic stylesheet to sub-app container - reAppendElement(stylesheetElement); - - /* - get the stored css rules from styled-components generated element, and the re-insert rules for them. - note that we must do this after style element had been added to document, which stylesheet would be associated to the document automatically. - check the spec https://www.w3.org/TR/cssom-1/#associated-css-style-sheet - */ - if (stylesheetElement instanceof HTMLStyleElement && isStyledComponentsLike(stylesheetElement)) { - const cssRules = getStyledElementCSSRules(stylesheetElement); - if (cssRules) { - // eslint-disable-next-line no-plusplus - for (let i = 0; i < cssRules.length; i++) { - const cssRule = cssRules[i]; - (stylesheetElement.sheet as CSSStyleSheet).insertRule(cssRule.cssText); + const appendSuccess = reAppendElement(stylesheetElement); + if (appendSuccess) { + /* + get the stored css rules from styled-components generated element, and the re-insert rules for them. + note that we must do this after style element had been added to document, which stylesheet would be associated to the document automatically. + check the spec https://www.w3.org/TR/cssom-1/#associated-css-style-sheet + */ + if (stylesheetElement instanceof HTMLStyleElement && isStyledComponentsLike(stylesheetElement)) { + const cssRules = getStyledElementCSSRules(stylesheetElement); + if (cssRules) { + // eslint-disable-next-line no-plusplus + for (let i = 0; i < cssRules.length; i++) { + const cssRule = cssRules[i]; + (stylesheetElement.sheet as CSSStyleSheet).insertRule(cssRule.cssText); + } } } } diff --git a/src/sandbox/patchers/dynamicAppend/forLooseSandbox.ts b/src/sandbox/patchers/dynamicAppend/forLooseSandbox.ts index 8642d09..1274627 100644 --- a/src/sandbox/patchers/dynamicAppend/forLooseSandbox.ts +++ b/src/sandbox/patchers/dynamicAppend/forLooseSandbox.ts @@ -70,10 +70,16 @@ export function patchLooseSandbox( // the dynamic style sheet would be removed automatically while unmoutting return function rebuild() { - rebuildCSSRules(dynamicStyleSheetElements, (stylesheetElement) => - // Using document.head.appendChild ensures that appendChild invocation can also directly use the HTMLHeadElement.prototype.appendChild method which is overwritten at mounting phase - document.head.appendChild.call(appWrapperGetter(), stylesheetElement), - ); + rebuildCSSRules(dynamicStyleSheetElements, (stylesheetElement) => { + const appWrapper = appWrapperGetter(); + if (!appWrapper.contains(stylesheetElement)) { + // Using document.head.appendChild ensures that appendChild invocation can also directly use the HTMLHeadElement.prototype.appendChild method which is overwritten at mounting phase + document.head.appendChild.call(appWrapper, stylesheetElement); + return true; + } + + return false; + }); // As the patcher will be invoked every mounting phase, we could release the cache for gc after rebuilding if (mounting) { diff --git a/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts b/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts index 407f63b..a4af062 100644 --- a/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts +++ b/src/sandbox/patchers/dynamicAppend/forStrictSandbox.ts @@ -94,17 +94,21 @@ export function patchStrictSandbox( unpatchDocumentCreate(); } - proxyAttachContainerConfigMap.delete(proxy); - recordStyledComponentsCSSRules(dynamicStyleSheetElements); // As now the sub app content all wrapped with a special id container, // the dynamic style sheet would be removed automatically while unmoutting return function rebuild() { - rebuildCSSRules(dynamicStyleSheetElements, (stylesheetElement) => - rawHeadAppendChild.call(appWrapperGetter(), stylesheetElement), - ); + rebuildCSSRules(dynamicStyleSheetElements, (stylesheetElement) => { + const appWrapper = appWrapperGetter(); + if (!appWrapper.contains(stylesheetElement)) { + rawHeadAppendChild.call(appWrapper, stylesheetElement); + return true; + } + + return false; + }); }; }; }