optimize source frame finding
This commit is contained in:
parent
c992e7f920
commit
bb3ad78e37
@ -22,6 +22,7 @@
|
|||||||
class FrameOffsetForwarder {
|
class FrameOffsetForwarder {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._started = false;
|
this._started = false;
|
||||||
|
this._frameCache = new Set();
|
||||||
|
|
||||||
this._forwardFrameOffset = (
|
this._forwardFrameOffset = (
|
||||||
window !== window.parent ?
|
window !== window.parent ?
|
||||||
@ -73,21 +74,12 @@ class FrameOffsetForwarder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onGetFrameOffset(offset, uniqueId, e) {
|
_onGetFrameOffset(offset, uniqueId, e) {
|
||||||
let sourceFrame = null;
|
const sourceFrame = this._findFrameWithContentWindow(e.source);
|
||||||
for (const frame of document.querySelectorAll('frame, iframe:not(.yomichan-float)')) {
|
|
||||||
if (frame.contentWindow !== e.source) { continue; }
|
|
||||||
sourceFrame = frame;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sourceFrame === null) {
|
if (sourceFrame === null) {
|
||||||
sourceFrame = this._getOpenShadowRootSourceFrame(e.source);
|
|
||||||
if (!sourceFrame) {
|
|
||||||
// closed shadow root etc.
|
// closed shadow root etc.
|
||||||
this._forwardFrameOffsetOrigin(null, uniqueId);
|
this._forwardFrameOffsetOrigin(null, uniqueId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const [forwardedX, forwardedY] = offset;
|
const [forwardedX, forwardedY] = offset;
|
||||||
const {x, y} = sourceFrame.getBoundingClientRect();
|
const {x, y} = sourceFrame.getBoundingClientRect();
|
||||||
@ -96,22 +88,38 @@ class FrameOffsetForwarder {
|
|||||||
this._forwardFrameOffset(offset, uniqueId);
|
this._forwardFrameOffset(offset, uniqueId);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getOpenShadowRootSourceFrame(sourceWindow) {
|
_findFrameWithContentWindow(contentWindow) {
|
||||||
const getShadowRootElements = (documentOrElement) => {
|
const elements = [
|
||||||
const elements = Array.from(documentOrElement.querySelectorAll('*'))
|
...this._frameCache,
|
||||||
.filter((el) => !!el.shadowRoot);
|
// will contain duplicates, but frame elements are cheap to handle
|
||||||
const childElements = elements
|
...document.querySelectorAll('frame, iframe:not(.yomichan-float)'),
|
||||||
.map((el) => el.shadowRoot)
|
document.documentElement
|
||||||
.map(getShadowRootElements);
|
];
|
||||||
elements.push(childElements.flat());
|
const ELEMENT_NODE = Node.ELEMENT_NODE;
|
||||||
|
while (elements.length > 0) {
|
||||||
|
const element = elements.shift();
|
||||||
|
if (element.contentWindow === contentWindow) {
|
||||||
|
this._frameCache.add(element);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
return elements.flat();
|
const shadowRoot = element.shadowRoot;
|
||||||
};
|
if (shadowRoot) {
|
||||||
|
for (const child of shadowRoot.children) {
|
||||||
|
if (child.nodeType === ELEMENT_NODE) {
|
||||||
|
elements.push(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return getShadowRootElements(document)
|
for (const child of element.children) {
|
||||||
.map((el) => Array.from(el.shadowRoot.querySelectorAll('frame, iframe:not(.yomichan-float)')))
|
if (child.nodeType === ELEMENT_NODE) {
|
||||||
.flat()
|
elements.push(child);
|
||||||
.find((el) => el.contentWindow === sourceWindow);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_forwardFrameOffsetParent(offset, uniqueId) {
|
_forwardFrameOffsetParent(offset, uniqueId) {
|
||||||
|
Loading…
Reference in New Issue
Block a user