Home / File/ ControlDominators.ts — react Source File

ControlDominators.ts — react Source File

Architecture documentation for ControlDominators.ts, a typescript file in the react codebase. 3 imports, 2 dependents.

File typescript BabelCompiler Validation 3 imports 2 dependents 4 functions

Entity Profile

Dependency Diagram

graph LR
  5d62162e_5fa5_1488_29bf_5150b4be53a0["ControlDominators.ts"]
  0423f759_97e0_9101_4634_ed555abc5ca9["index.ts"]
  5d62162e_5fa5_1488_29bf_5150b4be53a0 --> 0423f759_97e0_9101_4634_ed555abc5ca9
  b02a9daf_aca4_b66a_9b9b_0b739a8ca4aa["Dominator.ts"]
  5d62162e_5fa5_1488_29bf_5150b4be53a0 --> b02a9daf_aca4_b66a_9b9b_0b739a8ca4aa
  0732b54e_6e75_2208_9742_addaecfa3581["PostDominator"]
  5d62162e_5fa5_1488_29bf_5150b4be53a0 --> 0732b54e_6e75_2208_9742_addaecfa3581
  725143dd_a713_5e8e_fdf0_9c99de3b528f["InferReactivePlaces.ts"]
  725143dd_a713_5e8e_fdf0_9c99de3b528f --> 5d62162e_5fa5_1488_29bf_5150b4be53a0
  71d73648_b3a1_c2f2_a010_106a2a2c80f6["ValidateNoSetStateInEffects.ts"]
  71d73648_b3a1_c2f2_a010_106a2a2c80f6 --> 5d62162e_5fa5_1488_29bf_5150b4be53a0
  style 5d62162e_5fa5_1488_29bf_5150b4be53a0 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import {BlockId, computePostDominatorTree, HIRFunction, Place} from '../HIR';
import {PostDominator} from '../HIR/Dominator';

export type ControlDominators = (id: BlockId) => boolean;

/**
 * Returns an object that lazily calculates whether particular blocks are controlled
 * by values of interest. Which values matter are up to the caller.
 */
export function createControlDominators(
  fn: HIRFunction,
  isControlVariable: (place: Place) => boolean,
): ControlDominators {
  const postDominators = computePostDominatorTree(fn, {
    includeThrowsAsExitNode: false,
  });
  const postDominatorFrontierCache = new Map<BlockId, Set<BlockId>>();

  function isControlledBlock(id: BlockId): boolean {
    let controlBlocks = postDominatorFrontierCache.get(id);
    if (controlBlocks === undefined) {
      controlBlocks = postDominatorFrontier(fn, postDominators, id);
      postDominatorFrontierCache.set(id, controlBlocks);
    }
    for (const blockId of controlBlocks) {
      const controlBlock = fn.body.blocks.get(blockId)!;
      switch (controlBlock.terminal.kind) {
        case 'if':
        case 'branch': {
          if (isControlVariable(controlBlock.terminal.test)) {
            return true;
          }
          break;
        }
        case 'switch': {
          if (isControlVariable(controlBlock.terminal.test)) {
            return true;
          }
          for (const case_ of controlBlock.terminal.cases) {
            if (case_.test !== null && isControlVariable(case_.test)) {
              return true;
            }
          }
          break;
        }
      }
    }
    return false;
  }

  return isControlledBlock;
}

/*
 * Computes the post-dominator frontier of @param block. These are immediate successors of nodes that
 * post-dominate @param targetId and from which execution may not reach @param block. Intuitively, these
 * are the earliest blocks from which execution branches such that it may or may not reach the target block.
 */
function postDominatorFrontier(
  fn: HIRFunction,
  postDominators: PostDominator<BlockId>,
  targetId: BlockId,
): Set<BlockId> {
  const visited = new Set<BlockId>();
  const frontier = new Set<BlockId>();
  const targetPostDominators = postDominatorsOf(fn, postDominators, targetId);
  for (const blockId of [...targetPostDominators, targetId]) {
    if (visited.has(blockId)) {
      continue;
    }
    visited.add(blockId);
    const block = fn.body.blocks.get(blockId)!;
    for (const pred of block.preds) {
      if (!targetPostDominators.has(pred)) {
        // The predecessor does not always reach this block, we found an item on the frontier!
        frontier.add(pred);
      }
    }
  }
  return frontier;
}

function postDominatorsOf(
  fn: HIRFunction,
  postDominators: PostDominator<BlockId>,
  targetId: BlockId,
): Set<BlockId> {
  const result = new Set<BlockId>();
  const visited = new Set<BlockId>();
  const queue = [targetId];
  while (queue.length) {
    const currentId = queue.shift()!;
    if (visited.has(currentId)) {
      continue;
    }
    visited.add(currentId);
    const current = fn.body.blocks.get(currentId)!;
    for (const pred of current.preds) {
      const predPostDominator = postDominators.get(pred) ?? pred;
      if (predPostDominator === targetId || result.has(predPostDominator)) {
        result.add(pred);
      }
      queue.push(pred);
    }
  }
  return result;
}

Domain

Subdomains

Frequently Asked Questions

What does ControlDominators.ts do?
ControlDominators.ts is a source file in the react codebase, written in typescript. It belongs to the BabelCompiler domain, Validation subdomain.
What functions are defined in ControlDominators.ts?
ControlDominators.ts defines 4 function(s): createControlDominators, id, postDominatorFrontier, postDominatorsOf.
What does ControlDominators.ts depend on?
ControlDominators.ts imports 3 module(s): Dominator.ts, PostDominator, index.ts.
What files import ControlDominators.ts?
ControlDominators.ts is imported by 2 file(s): InferReactivePlaces.ts, ValidateNoSetStateInEffects.ts.
Where is ControlDominators.ts in the architecture?
ControlDominators.ts is located at compiler/packages/babel-plugin-react-compiler/src/Inference/ControlDominators.ts (domain: BabelCompiler, subdomain: Validation, directory: compiler/packages/babel-plugin-react-compiler/src/Inference).

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free