text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.compileGeneralSelector = void 0;
  var attributes_1 = require("./attributes");
  var pseudo_selectors_1 = require("./pseudo-selectors");
  /*
   * All available rules
   */
  function compileGeneralSelector(next, selector, options, context, compileToken) {
      var adapter = options.adapter, equals = options.equals;
      switch (selector.type) {
          case "pseudo-element":
              throw new Error("Pseudo-elements are not supported by css-select");
          case "attribute":
              return attributes_1.attributeRules[selector.action](next, selector, options);
          case "pseudo":
              return (0, pseudo_selectors_1.compilePseudoSelector)(next, selector, options, context, compileToken);
          // Tags
          case "tag":
              return function tag(elem) {
                  return adapter.getName(elem) === selector.name && next(elem);
              };
          // Traversal
          case "descendant":
              if (options.cacheResults === false ||
                  typeof WeakSet === "undefined") {
                  return function descendant(elem) {
                      var current = elem;
                      while ((current = adapter.getParent(current))) {
                          if (adapter.isTag(current) && next(current)) {
                              return true;
                          }
                      }
                      return false;
                  };
              }
              // @ts-expect-error `ElementNode` is not extending object
              // eslint-disable-next-line no-case-declarations
              var isFalseCache_1 = new WeakSet();
              return function cachedDescendant(elem) {
                  var current = elem;
                  while ((current = adapter.getParent(current))) {
                      if (!isFalseCache_1.has(current)) {
                          if (adapter.isTag(current) && next(current)) {
                              return true;
                          }
                          isFalseCache_1.add(current);
                      }
                  }
                  return false;
              };
          case "_flexibleDescendant":
              // Include element itself, only used while querying an array
              return function flexibleDescendant(elem) {
                  var current = elem;
                  do {
                      if (adapter.isTag(current) && next(current))
                          return true;
                  } while ((current = adapter.getParent(current)));
                  return false;
              };
          case "parent":
              return function parent(elem) {
                  return adapter
                      .getChildren(elem)
                      .some(function (elem) { return adapter.isTag(elem) && next(elem); });
              };
          case "child":
              return function child(elem) {
                  var parent = adapter.getParent(elem);
                  return parent != null && adapter.isTag(parent) && next(parent);
              };
          case "sibling":
              return function sibling(elem) {
                  var siblings = adapter.getSiblings(elem);
                  for (var i = 0; i < siblings.length; i++) {
                      var currentSibling = siblings[i];
                      if (equals(elem, currentSibling))
                          break;
                      if (adapter.isTag(currentSibling) && next(currentSibling)) {
                          return true;
                      }
                  }
                  return false;
              };
          case "adjacent":
              return function adjacent(elem) {
                  var siblings = adapter.getSiblings(elem);
                  var lastElement;
                  for (var i = 0; i < siblings.length; i++) {
                      var currentSibling = siblings[i];
                      if (equals(elem, currentSibling))
                          break;
                      if (adapter.isTag(currentSibling)) {
                          lastElement = currentSibling;
                      }
                  }
                  return !!lastElement && next(lastElement);
              };
          case "universal":
              return next;
      }
  }
  exports.compileGeneralSelector = compileGeneralSelector;
  