From 9fd21b4b81ca20937842f2aa2d1431c4456580a5 Mon Sep 17 00:00:00 2001 From: Alex Alekseyenko Date: Sun, 27 Dec 2020 08:36:48 -0800 Subject: [PATCH] Add isContainedWithin function for ShadowRoots Previously, `el.contains(e)` would return `false` if `e` was inside ShadowRoots. If `el.contains(e)` returns `false`, `isContainedWithin(e, el)` will instead check `e`'s root, and the root's root, and so on, until either `contains` returns `true` or the top of the tree is reached. --- content_scripts/utils.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/content_scripts/utils.js b/content_scripts/utils.js index f66dc3dca..ac8de6c26 100644 --- a/content_scripts/utils.js +++ b/content_scripts/utils.js @@ -255,6 +255,18 @@ function isExplicitlyRequested(element) { element.matches(runtime.conf.clickableSelector); } +function isContainedWithin(inner, outer) { + // check if outer element contains inner element, recursively + // (works even if inner element is inside ShadowRoots) + if (!inner) { + return false; + } + if (outer.contains(inner)) { + return true; + } + return isContainedWithin(inner.getRootNode().host, outer); +} + function filterOverlapElements(elements) { // filter out tiny elements elements = elements.filter(function(e) { @@ -265,7 +277,12 @@ function filterOverlapElements(elements) { return true; } else { var el = document.elementFromPoint(be.left + be.width/2, be.top + be.height/2); - return !el || el.shadowRoot && el.childElementCount === 0 || el.contains(e) || e.contains(el); + return ( + !el + || el.shadowRoot && el.childElementCount === 0 + || isContainedWithin(e, el) + || isContainedWithin(el, e) + ); } });