Skip to content

Commit

Permalink
fix(1.0.0-rc.6): fix the issue of parentNode in nest app
Browse files Browse the repository at this point in the history
  • Loading branch information
bailicangdu committed Jul 27, 2024
1 parent bcc43e4 commit 5b3a4b8
Show file tree
Hide file tree
Showing 8 changed files with 20 additions and 68 deletions.
14 changes: 0 additions & 14 deletions dev/children/vite2/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,6 @@
window.document.domain = 'localhost'
console.log('子应用修改了 window.document.domain')
</script> -->
<!-- 测试 systemjs-importmap -->
<script type="systemjs-importmap">
{
"imports": {
"vue": "https://cdn.bootcss.com/vue/2.6.11/vue.js"
}
}
</script>
<script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>
<script>
System.import('vue').then((res) => {
console.log('systemjs-importmap:', res)
})
</script>
</head>
<body>
<div id="app"></div>
Expand Down
2 changes: 1 addition & 1 deletion dev/main-react16/src/pages/angular11/angular11.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function Angular11 () {
inline
// disableScopecss
// keep-alive
// iframe
iframe
// disable-memory-router
>
</micro-app>
Expand Down
2 changes: 1 addition & 1 deletion dev/main-react16/src/pages/angular14/angular14.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function Angular14 () {
// disableScopecss
// keep-alive
// esmodule
// iframe
iframe
>
</micro-app>
</div>
Expand Down
12 changes: 3 additions & 9 deletions src/libs/global_env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,8 @@ declare global {
__MICRO_APP_BASE_APPLICATION__?: boolean
__REACT_ERROR_OVERLAY_GLOBAL_HOOK__: boolean
rawLocation: Location
rawWindow: Window
rawDocument: Document
Document: any
Element: any,
Node: any,
EventTarget: any,
HTMLElement: HTMLElement,
DocumentFragment: any,
rawWindow: any
rawDocument: any
}
}

Expand Down Expand Up @@ -100,7 +94,7 @@ export function initGlobalEnv (): void {
const rawGetElementsByName = rawRootDocument.prototype.getElementsByName

// TODO: 将ImageProxy移出去
const ImageProxy = new Proxy(Image, {
const ImageProxy = new Proxy(rawWindow.Image, {
construct (Target, args): HTMLImageElement {
return updateElementInfo(new Target(...args), getCurrentAppName())
},
Expand Down
2 changes: 1 addition & 1 deletion src/libs/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export function isPromise (target: unknown): target is Promise<unknown> {

// is bind function
export function isBoundFunction (target: unknown): boolean {
return isFunction(target) && target.name.indexOf('bound ') === 0 && !target.hasOwnProperty('prototype')
return isFunction(target) && target.name?.indexOf('bound ') === 0 && !target.hasOwnProperty('prototype')
}

// is constructor function
Expand Down
40 changes: 2 additions & 38 deletions src/sandbox/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import globalEnv from '../libs/global_env'
import {
defer,
isNode,
rawDefineProperty,
rawDefineProperties,
isMicroAppBody,
getPreventSetState,
throttleDeferForIframeAppName,
} from '../libs/utils'
import {
appInstanceMap,
Expand Down Expand Up @@ -106,42 +106,6 @@ export function fixReactHMRConflict (app: AppInterface): void {
}
}

/**
* reDefine parentNode of html (just for iframe sandbox)
* Scenes:
* 1. element-ui@2/lib/utils/popper.js
* var parent = element.parentNode;
* // root is child app window
* if (parent === root.document) ...
*/
export function throttleDeferForParentNode (microDocument: Document | null): void {
if (microDocument) {
const html = globalEnv.rawDocument.firstElementChild
if (html.parentNode !== microDocument) {
setParentNode(html, microDocument)
defer(() => {
setParentNode(html, globalEnv.rawDocument)
})
}
}
}

/**
* Modify the point of parentNode
* @param target target Node
* @param value parentNode
*/
export function setParentNode (target: Node, value: Document | Element): void {
const descriptor = Object.getOwnPropertyDescriptor(target, 'parentNode')
if (!descriptor || descriptor.configurable) {
rawDefineProperty(target, 'parentNode', {
configurable: true,
enumerable: true,
value,
})
}
}

/**
* update dom tree of target dom
* @param container target dom
Expand Down Expand Up @@ -251,7 +215,7 @@ export function getIframeParentNodeDesc (
configurable: true,
enumerable: true,
get (this: Node) {
throttleDeferForParentNode(this.ownerDocument)
throttleDeferForIframeAppName(appName)
const result: ParentNode = parentNodeDesc.get?.call(this)
/**
* If parentNode is <micro-app-body>, return rawDocument.body
Expand Down
10 changes: 9 additions & 1 deletion src/sandbox/bind_function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ function isConstructorFunction (value: FunctionConstructor & {__MICRO_APP_IS_CON

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export default function bindFunctionToRawTarget<T = Window, B = unknown> (value: any, rawTarget: T, key = 'WINDOW'): B {
if (isFunction(value) && !isConstructorFunction(value) && !isBoundedFunction(value)) {
/**
* In safari, nest app like: A -> B -> C
* if B is iframe sandbox, and C is with sandbox, same property of document in C is abnormal
* e.g:
* document.all:
* - typeof document.all ==> 'function'
* - document.all.bind ==> undefined
*/
if (isFunction(value) && !isConstructorFunction(value) && !isBoundedFunction(value) && value.bind) {
const cacheKey = `__MICRO_APP_BOUND_${key}_FUNCTION__`
if (value[cacheKey]) return value[cacheKey]

Expand Down
6 changes: 3 additions & 3 deletions src/source/patch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -599,13 +599,13 @@ export function patchElementAndDocument (): void {
* // root is child app window, so root.document is proxyDocument or microDocument
* if (element.parentNode === root.document) ...
*/
const currentAppName = getCurrentAppName()
// if this is html element and currentAppName exists, html.parentNode will return proxyDocument
const currentAppName = getIframeCurrentAppName() || getCurrentAppName()
if (currentAppName && this === globalEnv.rawDocument.firstElementChild) {
const microDocument = appInstanceMap.get(currentAppName)?.sandBox?.proxyWindow?.document
if (microDocument) return microDocument
}
const result = globalEnv.rawParentNodeDesc.get.call(this) as Node
// NOTE: run after hijack html.parentNode
const result = globalEnv.rawParentNodeDesc.get.call(this)
/**
* If parentNode is <micro-app-body>, return rawDocument.body
* Scenes:
Expand Down

0 comments on commit 5b3a4b8

Please sign in to comment.