From 918df59de0f4a3cf7ca9c48486290ad0e93e99f0 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Wed, 9 Jun 2021 13:35:04 +0200 Subject: [PATCH] fix(iframe): correct highlighter position --- packages/app-backend-core/src/hook.ts | 21 +++++++++------ .../app-backend-vue2/src/components/el.ts | 27 ++++++++++++++++--- .../app-backend-vue3/src/components/el.ts | 25 +++++++++++++++-- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/packages/app-backend-core/src/hook.ts b/packages/app-backend-core/src/hook.ts index e6546c508..3124346f6 100644 --- a/packages/app-backend-core/src/hook.ts +++ b/packages/app-backend-core/src/hook.ts @@ -8,7 +8,7 @@ * * @param {Window|global} target */ -export function installHook (target, iframe = false) { +export function installHook (target, isIframe = false) { let listeners = {} let iframeChecks = 0 @@ -16,12 +16,17 @@ export function installHook (target, iframe = false) { const iframes = document.querySelectorAll('iframe') for (const iframe of iframes) { try { - if (iframe.getAttribute('data-vdevtools-injection')) continue - iframe.setAttribute('data-vdevtools-injection', 'true') - const script = iframe.contentDocument.createElement('script') - script.textContent = ';(' + installHook.toString() + ')(window, true)' - iframe.contentDocument.documentElement.appendChild(script) - script.parentNode.removeChild(script) + if ((iframe as any).__vdevtools__injected) continue + (iframe as any).__vdevtools__injected = true + const inject = () => { + (iframe.contentWindow as any).__VUE_DEVTOOLS_IFRAME__ = iframe + const script = iframe.contentDocument.createElement('script') + script.textContent = ';(' + installHook.toString() + ')(window, true)' + iframe.contentDocument.documentElement.appendChild(script) + script.parentNode.removeChild(script) + } + inject() + iframe.addEventListener('load', () => inject()) } catch (e) { // Ignore } @@ -40,7 +45,7 @@ export function installHook (target, iframe = false) { let hook - if (iframe) { + if (isIframe) { const sendToParent = cb => { try { const hook = (window.parent as any).__VUE_DEVTOOLS_GLOBAL_HOOK__ diff --git a/packages/app-backend-vue2/src/components/el.ts b/packages/app-backend-vue2/src/components/el.ts index a86391e6d..5fb63d5f6 100644 --- a/packages/app-backend-vue2/src/components/el.ts +++ b/packages/app-backend-vue2/src/components/el.ts @@ -25,13 +25,14 @@ function mergeRects (a, b) { if (!a.right || b.right > a.right) { a.right = b.right } + return a } /** * Get the client rect for an instance. */ export function getInstanceOrVnodeRect (instance) { - const el = instance.subTree ? instance.subTree.el : instance.$el || instance.elm + const el = instance.$el || instance.elm if (!isBrowser) { // TODO: Find position from instance or a vnode (for functional components). @@ -43,9 +44,9 @@ export function getInstanceOrVnodeRect (instance) { } if (instance._isFragment) { - return getLegacyFragmentRect(instance) + return addIframePosition(getLegacyFragmentRect(instance), getElWindow(instance.$root.$el)) } else if (el.nodeType === 1) { - return el.getBoundingClientRect() + return addIframePosition(el.getBoundingClientRect(), getElWindow(el)) } } @@ -95,3 +96,23 @@ export function findRelatedComponent (el) { } return el.__vue__ } + +function getElWindow (el: HTMLElement) { + return el.ownerDocument.defaultView +} + +function addIframePosition (bounds, win: any) { + if (win.__VUE_DEVTOOLS_IFRAME__) { + const rect = mergeRects(createRect(), bounds) + const iframeBounds = win.__VUE_DEVTOOLS_IFRAME__.getBoundingClientRect() + rect.top += iframeBounds.top + rect.bottom += iframeBounds.top + rect.left += iframeBounds.left + rect.right += iframeBounds.left + if (win.parent) { + return addIframePosition(rect, win.parent) + } + return rect + } + return bounds +} diff --git a/packages/app-backend-vue3/src/components/el.ts b/packages/app-backend-vue3/src/components/el.ts index 6eace47a1..fb9e8e8d1 100644 --- a/packages/app-backend-vue3/src/components/el.ts +++ b/packages/app-backend-vue3/src/components/el.ts @@ -47,9 +47,9 @@ export function getInstanceOrVnodeRect (instance) { } if (isFragment(instance)) { - return getFragmentRect(instance.subTree) + return addIframePosition(getFragmentRect(instance.subTree), getElWindow(el)) } else if (el.nodeType === 1) { - return el.getBoundingClientRect() + return addIframePosition(el.getBoundingClientRect(), getElWindow(el)) } } @@ -78,6 +78,7 @@ function mergeRects (a, b) { if (!a.right || b.right > a.right) { a.right = b.right } + return a } let range @@ -120,3 +121,23 @@ function getFragmentRect (vnode) { return rect } + +function getElWindow (el: HTMLElement) { + return el.ownerDocument.defaultView +} + +function addIframePosition (bounds, win: any) { + if (win.__VUE_DEVTOOLS_IFRAME__) { + const rect = mergeRects(createRect(), bounds) + const iframeBounds = win.__VUE_DEVTOOLS_IFRAME__.getBoundingClientRect() + rect.top += iframeBounds.top + rect.bottom += iframeBounds.top + rect.left += iframeBounds.left + rect.right += iframeBounds.left + if (win.parent) { + return addIframePosition(rect, win.parent) + } + return rect + } + return bounds +}