From 941077a25ccd233d435398246312d3b388493d5a Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 4 Dec 2023 08:02:07 -0500 Subject: [PATCH] Support shadow-piercing combinator `>>>` in `trusted-click-element` Related issue: https://github.com/uBlockOrigin/uBlock-issues/issues/2971 Example usage: ...##+js(trusted-trusted-click-element, #cmpwrapper >>> .cmpboxbtnyes) The substring before ` >>> ` must select an element with a non-null shadow root, in which case the substring after ` >>> ` will be used to find the element in the targeted shadow root. ` >>> ` can be used recursively when multiple shadow root must be pierced. --- assets/resources/scriptlets.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/assets/resources/scriptlets.js b/assets/resources/scriptlets.js index 45d8fdae3..ceda6662b 100644 --- a/assets/resources/scriptlets.js +++ b/assets/resources/scriptlets.js @@ -4077,10 +4077,21 @@ function trustedClickElement( ? ((...args) => { safe.uboLog(...args); }) : (( ) => { }); + const querySelectorEx = (selector, context = document) => { + const pos = selector.indexOf(' >>> '); + if ( pos === -1 ) { return context.querySelector(selector); } + const outside = selector.slice(0, pos).trim(); + const inside = selector.slice(pos + 5).trim(); + const elem = context.querySelector(outside); + if ( elem === null ) { return null; } + const shadowRoot = elem.shadowRoot; + return shadowRoot && querySelectorEx(inside, shadowRoot); + }; + const selectorList = selectors.split(/\s*,\s*/) .filter(s => { try { - void document.querySelector(s); + void querySelectorEx(s); } catch(_) { return false; } @@ -4154,7 +4165,7 @@ function trustedClickElement( if ( Date.now() < tnext ) { return next(); } const selector = selectorList.shift(); if ( selector === undefined ) { return terminate(); } - const elem = document.querySelector(selector); + const elem = querySelectorEx(selector); if ( elem === null ) { selectorList.unshift(selector); return next(true);