matchedRulesForInvalidate method

List<CSSRule> matchedRulesForInvalidate(
  1. RuleSet ruleSet,
  2. Element element
)

Implementation

List<CSSRule> matchedRulesForInvalidate(RuleSet ruleSet, Element element) {
  List<CSSRule> matchedRules = [];
  // Reuse a single evaluator per call.
  final SelectorEvaluator evaluator = SelectorEvaluator();
  final _AncestorTokenSet? ancestorTokens = DebugFlags.enableCssAncestryFastPath
      ? _buildAncestorTokens(element)
      : null;

  if (ruleSet.isEmpty) return matchedRules;

  // NOTE: id/class/attribute selectors are handled via document indices in
  // StyleNodeManager.invalidateElementStyle(). Do not evaluate them here.

  // tag selectors (optional)
  if (!DebugFlags.enableCssInvalidateSkipTag) {
    final String tagLookup = element.tagName.toUpperCase();
    final listTag = ruleSet.tagRules[tagLookup];
    matchedRules.addAll(_collectMatchingRulesForList(
      listTag,
      element,
      evaluator: evaluator,
      enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
      ancestorTokens: ancestorTokens,
    ));
    if (matchedRules.isNotEmpty) gotoReturn(matchedRules);
  }

  // universal (optional + capped or heuristic skip)
  final bool skipUniversal = DebugFlags.enableCssInvalidateSkipUniversal ||
      (DebugFlags.enableCssInvalidateUniversalHeuristics &&
          ruleSet.universalRules.length > DebugFlags.cssInvalidateUniversalSkipThreshold);
  if (!skipUniversal) {
    final int cap = DebugFlags.cssInvalidateUniversalCap;
    if (cap > 0 && ruleSet.universalRules.length > cap) {
      matchedRules.addAll(_collectMatchingRulesForList(
        ruleSet.universalRules.take(cap).toList(),
        element,
        evaluator: evaluator,
        enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
        ancestorTokens: ancestorTokens,
      ));
    } else {
      matchedRules.addAll(_collectMatchingRulesForList(
        ruleSet.universalRules,
        element,
        evaluator: evaluator,
        enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
        ancestorTokens: ancestorTokens,
      ));
    }
    if (matchedRules.isNotEmpty) gotoReturn(matchedRules);
  }

  // Legacy pseudo rules (e.g., ::before/::after)
  if (ruleSet.pseudoRules.isNotEmpty) {
    matchedRules.addAll(_collectMatchingRulesForList(
      ruleSet.pseudoRules,
      element,
      evaluator: evaluator,
      enableAncestryFastPath: false,
      ancestorTokens: null,
      includePseudo: true,
    ));
    if (matchedRules.isNotEmpty) gotoReturn(matchedRules);
  }


  return matchedRules;
}