🐛 dynamicStyleElement array should not be clear after remount (#1054)

This commit is contained in:
Kuitos 2020-11-05 20:07:48 +08:00 committed by GitHub
parent 3b98d6d708
commit 006536dc19
3 changed files with 35 additions and 24 deletions

View File

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

View File

@ -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) {

View File

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