matchedRulesForInvalidate method

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

Implementation

List<CSSRule> matchedRulesForInvalidate(RuleSet ruleSet, Element element) {
  final List<CSSStyleRule> matchedRules = <CSSStyleRule>[];
  // Reuse a single evaluator per call.
  final SelectorEvaluator evaluator = SelectorEvaluator();
  final SelectorAncestorTokenSet? 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];
    _collectMatchingRulesForList(
      listTag,
      element,
      evaluator: evaluator,
      enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
      ancestorTokens: ancestorTokens,
      matchedRules: matchedRules,
    );
    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) {
      _collectMatchingRulesForList(
        ruleSet.universalRules.take(cap).toList(),
        element,
        evaluator: evaluator,
        enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
        ancestorTokens: ancestorTokens,
        matchedRules: matchedRules,
      );
    } else {
      _collectMatchingRulesForList(
        ruleSet.universalRules,
        element,
        evaluator: evaluator,
        enableAncestryFastPath: DebugFlags.enableCssAncestryFastPath,
        ancestorTokens: ancestorTokens,
        matchedRules: matchedRules,
      );
    }
    if (matchedRules.isNotEmpty) gotoReturn(matchedRules);
  }

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

  return matchedRules.cast<CSSRule>();
}