From 8bda7a236f227b621f17eb4e7e6023f210134f8a Mon Sep 17 00:00:00 2001 From: HoJeong Go Date: Sun, 29 Mar 2026 11:07:58 +0900 Subject: [PATCH] optimise: utilise `Element.prototype.closest` for `:upward` This tries to utilise `Element.prototype.closest` which is widely available: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest for `:upward` pseudo-class. --- .../adblocker-extended-selectors/src/eval.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/adblocker-extended-selectors/src/eval.ts b/packages/adblocker-extended-selectors/src/eval.ts index a4fc1fddb9..d3276a4e23 100644 --- a/packages/adblocker-extended-selectors/src/eval.ts +++ b/packages/adblocker-extended-selectors/src/eval.ts @@ -6,6 +6,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +import { classifySelector, SelectorType } from './extended.js'; import type { AST, Complex, PseudoClass } from './types.js'; const createXpathExpression = (function () { @@ -23,6 +24,26 @@ const createXpathExpression = (function () { }; })(); +const cachedIsExtended = (function () { + const extended: string[] = []; + const standard: string[] = []; + + return function classify(selector: string) { + if (extended.includes(selector)) { + return true; + } + if (standard.includes(selector)) { + return false; + } + if (classifySelector(selector) === SelectorType.Extended) { + extended.push(selector); + return true; + } + standard.push(selector); + return false; + }; +})(); + /** * Evaluates an XPath expression and returns matching Element nodes. * @param element - The context element for XPath evaluation @@ -365,6 +386,11 @@ function transpose(element: Element, selector: AST): Element[] | null { return [parentElement]; } } + } else if (cachedIsExtended(argument) === false) { + const closest = element.closest(argument); + if (closest !== null) { + return [closest]; + } } else { while ((parentElement = parentElement.parentElement) !== null) { if (parentElement.matches(argument)) {