tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GetQueryHandler.ts (2341B)


      1 /**
      2 * @license
      3 * Copyright 2023 Google Inc.
      4 * SPDX-License-Identifier: Apache-2.0
      5 */
      6 
      7 import {ARIAQueryHandler} from '../cdp/AriaQueryHandler.js';
      8 
      9 import {CSSQueryHandler} from './CSSQueryHandler.js';
     10 import {customQueryHandlers} from './CustomQueryHandler.js';
     11 import {PierceQueryHandler} from './PierceQueryHandler.js';
     12 import {PQueryHandler} from './PQueryHandler.js';
     13 import {parsePSelectors} from './PSelectorParser.js';
     14 import type {QueryHandler} from './QueryHandler.js';
     15 import {PollingOptions} from './QueryHandler.js';
     16 import {TextQueryHandler} from './TextQueryHandler.js';
     17 import {XPathQueryHandler} from './XPathQueryHandler.js';
     18 
     19 const BUILTIN_QUERY_HANDLERS = {
     20  aria: ARIAQueryHandler,
     21  pierce: PierceQueryHandler,
     22  xpath: XPathQueryHandler,
     23  text: TextQueryHandler,
     24 } as const;
     25 
     26 const QUERY_SEPARATORS = ['=', '/'];
     27 
     28 /**
     29 * @internal
     30 */
     31 export function getQueryHandlerAndSelector(selector: string): {
     32  updatedSelector: string;
     33  polling: PollingOptions;
     34  QueryHandler: typeof QueryHandler;
     35 } {
     36  for (const handlerMap of [
     37    customQueryHandlers.names().map(name => {
     38      return [name, customQueryHandlers.get(name)!] as const;
     39    }),
     40    Object.entries(BUILTIN_QUERY_HANDLERS),
     41  ]) {
     42    for (const [name, QueryHandler] of handlerMap) {
     43      for (const separator of QUERY_SEPARATORS) {
     44        const prefix = `${name}${separator}`;
     45        if (selector.startsWith(prefix)) {
     46          selector = selector.slice(prefix.length);
     47          return {
     48            updatedSelector: selector,
     49            polling:
     50              name === 'aria' ? PollingOptions.RAF : PollingOptions.MUTATION,
     51            QueryHandler,
     52          };
     53        }
     54      }
     55    }
     56  }
     57  try {
     58    const [pSelector, isPureCSS, hasPseudoClasses, hasAria] =
     59      parsePSelectors(selector);
     60    if (isPureCSS) {
     61      return {
     62        updatedSelector: selector,
     63        polling: hasPseudoClasses
     64          ? PollingOptions.RAF
     65          : PollingOptions.MUTATION,
     66        QueryHandler: CSSQueryHandler,
     67      };
     68    }
     69    return {
     70      updatedSelector: JSON.stringify(pSelector),
     71      polling: hasAria ? PollingOptions.RAF : PollingOptions.MUTATION,
     72      QueryHandler: PQueryHandler,
     73    };
     74  } catch {
     75    return {
     76      updatedSelector: selector,
     77      polling: PollingOptions.MUTATION,
     78      QueryHandler: CSSQueryHandler,
     79    };
     80  }
     81 }