🐛 prevent element from processing multi times in nest sandbox (#2471)

This commit is contained in:
Kuitos 2023-04-18 21:21:21 +08:00 committed by GitHub
parent 8bb5c948be
commit d9200ff5f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 3 deletions

View File

@ -269,7 +269,7 @@ function getOverwrittenAppendChildOrInsertBefore(opts: {
case SCRIPT_TAG_NAME: { case SCRIPT_TAG_NAME: {
const { src, text } = element as HTMLScriptElement; const { src, text } = element as HTMLScriptElement;
// some script like jsonp maybe not support cors which should't use execScripts // some script like jsonp maybe not support cors which shouldn't use execScripts
if ((excludeAssetFilter && src && excludeAssetFilter(src)) || !isExecutableScriptType(element)) { if ((excludeAssetFilter && src && excludeAssetFilter(src)) || !isExecutableScriptType(element)) {
return rawDOMAppendOrInsertBefore.call(this, element, refChild) as T; return rawDOMAppendOrInsertBefore.call(this, element, refChild) as T;
} }

View File

@ -71,7 +71,7 @@ export function patchLooseSandbox(
recordStyledComponentsCSSRules(dynamicStyleSheetElements); recordStyledComponentsCSSRules(dynamicStyleSheetElements);
// As now the sub app content all wrapped with a special id container, // As now the sub app content all wrapped with a special id container,
// the dynamic style sheet would be removed automatically while unmoutting // the dynamic style sheet would be removed automatically while unmounting
return function rebuild() { return function rebuild() {
rebuildCSSRules(dynamicStyleSheetElements, (stylesheetElement) => { rebuildCSSRules(dynamicStyleSheetElements, (stylesheetElement) => {

View File

@ -18,6 +18,13 @@ import {
styleElementTargetSymbol, styleElementTargetSymbol,
} from './common'; } from './common';
const elementAttachedSymbol = Symbol('attachedApp');
declare global {
interface HTMLElement {
[elementAttachedSymbol]: string;
}
}
// Get native global window with a sandbox disgusted way, thus we could share it between qiankun instances🤪 // Get native global window with a sandbox disgusted way, thus we could share it between qiankun instances🤪
Object.defineProperty(nativeGlobal, '__proxyAttachContainerConfigMap__', { enumerable: false, writable: true }); Object.defineProperty(nativeGlobal, '__proxyAttachContainerConfigMap__', { enumerable: false, writable: true });
@ -41,9 +48,19 @@ function patchDocument(cfg: { sandbox: SandBox; speedy: boolean }) {
const { sandbox, speedy } = cfg; const { sandbox, speedy } = cfg;
const attachElementToProxy = (element: HTMLElement, proxy: Window) => { const attachElementToProxy = (element: HTMLElement, proxy: Window) => {
// If this element has been processed by a sandbox, it should not be processed again.
// This usually occurs in the nested scenario, where an element is repeatedly processed by the sandbox in the nested chain.
if (element[elementAttachedSymbol]) return;
const proxyContainerConfig = proxyAttachContainerConfigMap.get(proxy); const proxyContainerConfig = proxyAttachContainerConfigMap.get(proxy);
if (proxyContainerConfig) { if (proxyContainerConfig) {
elementAttachContainerConfigMap.set(element, proxyContainerConfig); elementAttachContainerConfigMap.set(element, proxyContainerConfig);
Object.defineProperty(element, elementAttachedSymbol, {
enumerable: false,
configurable: false,
writable: false,
value: proxy.name,
});
} }
}; };
@ -67,7 +84,7 @@ function patchDocument(cfg: { sandbox: SandBox; speedy: boolean }) {
const value = (<any>target)[p]; const value = (<any>target)[p];
// must rebind the function to the target otherwise it will cause illegal invocation error // must rebind the function to the target otherwise it will cause illegal invocation error
if (typeof value === 'function' && !isBoundedFunction(value)) { if (typeof value === 'function' && !isBoundedFunction(value)) {
return function proxiedFunction(...args: unknown[]) { return function proxyFunction(...args: unknown[]) {
return value.call(target, ...args.map((arg) => (arg === receiver ? target : arg))); return value.call(target, ...args.map((arg) => (arg === receiver ? target : arg)));
}; };
} }