From be205d243cdeffddaecbeedb3dc6b2c27d806233 Mon Sep 17 00:00:00 2001 From: yiludege Date: Tue, 6 Sep 2022 17:59:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dsvg=E5=9C=A8append?= =?UTF-8?q?=E5=88=B0=E5=85=83=E7=B4=A0=E4=B9=8B=E5=90=8Eownerdocument?= =?UTF-8?q?=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98=20(#132)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/wujie-core/src/effect.ts | 15 +++++++----- packages/wujie-core/src/iframe.ts | 39 ++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/packages/wujie-core/src/effect.ts b/packages/wujie-core/src/effect.ts index ef8cfd7c5..e559e3c72 100644 --- a/packages/wujie-core/src/effect.ts +++ b/packages/wujie-core/src/effect.ts @@ -9,7 +9,7 @@ import { rawRemoveEventListener, } from "./common"; import { isFunction, isHijackingTag, requestIdleCallback, error, warn, nextTick, getCurUrl } from "./utils"; -import { insertScriptToIframe } from "./iframe"; +import { insertScriptToIframe, patchElementEffect } from "./iframe"; import Wujie from "./sandbox"; import { getPatchStyleElements } from "./shadow"; import { getCssLoader, getEffectLoaders, isMatchUrl } from "./plugin"; @@ -70,12 +70,12 @@ function handleStylesheetElementPatch(stylesheetElement: HTMLStyleElement & { _p * 劫持处理样式元素的属性 */ function patchStylesheetElement( - stylesheetElement: HTMLStyleElement & { _hasPatch?: boolean }, + stylesheetElement: HTMLStyleElement & { _hasPatchStyle?: boolean }, cssLoader: (code: string, url: string, base: string) => string, sandbox: Wujie, curUrl: string ) { - if (stylesheetElement._hasPatch) return; + if (stylesheetElement._hasPatchStyle) return; const innerHTMLDesc = Object.getOwnPropertyDescriptor(Element.prototype, "innerHTML"); const innerTextDesc = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerText"); const textContentDesc = Object.getOwnPropertyDescriptor(Node.prototype, "textContent"); @@ -131,7 +131,7 @@ function patchStylesheetElement( } else return rawAppendChild(node); }, }, - _hasPatch: { get: () => true }, + _hasPatchStyle: { get: () => true }, }); } @@ -148,11 +148,14 @@ function rewriteAppendOrInsertChild(opts: { const { rawDOMAppendOrInsertBefore, wujieId } = opts; const sandbox = getWujieById(wujieId); + const { styleSheetElements, replace, fetch, plugins, iframe, lifecycles, proxyLocation } = sandbox; + if (!isHijackingTag(element.tagName) || !wujieId) { - return rawDOMAppendOrInsertBefore.call(this, element, refChild) as T; + const res = rawDOMAppendOrInsertBefore.call(this, element, refChild) as T; + patchElementEffect(element, iframe.contentWindow); + return res; } - const { styleSheetElements, replace, fetch, plugins, iframe, lifecycles, proxyLocation } = sandbox; const iframeDocument = iframe.contentDocument; const curUrl = getCurUrl(proxyLocation); diff --git a/packages/wujie-core/src/iframe.ts b/packages/wujie-core/src/iframe.ts index a24deefc2..bc4013801 100644 --- a/packages/wujie-core/src/iframe.ts +++ b/packages/wujie-core/src/iframe.ts @@ -520,15 +520,29 @@ function patchDocumentEffect(iframeWindow: Window): void { /** * patch Node effect + * 1、处理 getRootNode + * 2、处理 appendChild、insertBefore,当插入的节点为 svg 时,createElement 的 patch 会被去除,需要重新 patch * @param iframeWindow */ function patchNodeEffect(iframeWindow: Window): void { const rawGetRootNode = iframeWindow.Node.prototype.getRootNode; + const rawAppendChild = iframeWindow.Node.prototype.appendChild; + const RawInsertRule = iframeWindow.Node.prototype.insertBefore; iframeWindow.Node.prototype.getRootNode = function (options?: GetRootNodeOptions): Node { const rootNode = rawGetRootNode.call(this, options); if (rootNode === iframeWindow.__WUJIE.shadowRoot) return iframeWindow.document; else return rootNode; }; + iframeWindow.Node.prototype.appendChild = function (node: T): T { + const res = rawAppendChild.call(this, node); + patchElementEffect(node, iframeWindow); + return res; + }; + iframeWindow.Node.prototype.insertBefore = function (node: T, child: Node | null): T { + const res = RawInsertRule.call(this, node, child); + patchElementEffect(node, iframeWindow); + return res; + }; } /** @@ -601,16 +615,23 @@ function stopIframeLoading(iframeWindow: Window, url: string) { }); } -export function patchElementEffect(element: HTMLElement | ShadowRoot, iframeWindow: Window): void { +export function patchElementEffect( + element: (HTMLElement | Node | ShadowRoot) & { _hasPatch?: boolean }, + iframeWindow: Window +): void { const proxyLocation = iframeWindow.__WUJIE.proxyLocation as Location; - Object.defineProperty(element, "baseURI", { - configurable: true, - get: () => proxyLocation.protocol + "//" + proxyLocation.host + proxyLocation.pathname, - set: undefined, - }); - Object.defineProperty(element, "ownerDocument", { - configurable: true, - get: () => iframeWindow.document, + if (element._hasPatch) return; + Object.defineProperties(element, { + baseURI: { + configurable: true, + get: () => proxyLocation.protocol + "//" + proxyLocation.host + proxyLocation.pathname, + set: undefined, + }, + ownerDocument: { + configurable: true, + get: () => iframeWindow.document, + }, + _hasPatch: { get: () => true }, }); }