Home / File/ AlignObjectMethodScopes.ts — react Source File

AlignObjectMethodScopes.ts — react Source File

Architecture documentation for AlignObjectMethodScopes.ts, a typescript file in the react codebase. 6 imports, 0 dependents.

File typescript BabelCompiler Validation 6 imports 2 functions

Entity Profile

Dependency Diagram

graph LR
  ad600d8a_ade3_8a40_a17a_ccb4623a8608["AlignObjectMethodScopes.ts"]
  0423f759_97e0_9101_4634_ed555abc5ca9["index.ts"]
  ad600d8a_ade3_8a40_a17a_ccb4623a8608 --> 0423f759_97e0_9101_4634_ed555abc5ca9
  2f3caf55_cc64_415c_55dd_9771ba7dc210["visitors.ts"]
  ad600d8a_ade3_8a40_a17a_ccb4623a8608 --> 2f3caf55_cc64_415c_55dd_9771ba7dc210
  b2fc2985_a7ba_9865_c2a3_2a7531f27d44["eachInstructionValueOperand"]
  ad600d8a_ade3_8a40_a17a_ccb4623a8608 --> b2fc2985_a7ba_9865_c2a3_2a7531f27d44
  edec7689_7b1d_03c9_9cbb_bb9b0552bc30["DisjointSet.ts"]
  ad600d8a_ade3_8a40_a17a_ccb4623a8608 --> edec7689_7b1d_03c9_9cbb_bb9b0552bc30
  1765a682_3028_4441_b26f_c712ca2597d5["DisjointSet"]
  ad600d8a_ade3_8a40_a17a_ccb4623a8608 --> 1765a682_3028_4441_b26f_c712ca2597d5
  2ed45bcd_6c82_3ccd_0e20_fa96b5111055[".."]
  ad600d8a_ade3_8a40_a17a_ccb4623a8608 --> 2ed45bcd_6c82_3ccd_0e20_fa96b5111055
  style ad600d8a_ade3_8a40_a17a_ccb4623a8608 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 {CompilerError} from '..';
import {
  GeneratedSource,
  HIRFunction,
  Identifier,
  ReactiveScope,
  makeInstructionId,
} from '../HIR';
import {eachInstructionValueOperand} from '../HIR/visitors';
import DisjointSet from '../Utils/DisjointSet';

/**
 * Align scopes of object method values to that of their enclosing object expressions.
 * To produce a well-formed JS program in Codegen, object methods and object expressions
 * must be in the same ReactiveBlock as object method definitions must be inlined.
 */

function findScopesToMerge(fn: HIRFunction): DisjointSet<ReactiveScope> {
  const objectMethodDecls: Set<Identifier> = new Set();
  const mergeScopesBuilder = new DisjointSet<ReactiveScope>();

  for (const [_, block] of fn.body.blocks) {
    for (const {lvalue, value} of block.instructions) {
      if (value.kind === 'ObjectMethod') {
        objectMethodDecls.add(lvalue.identifier);
      } else if (value.kind === 'ObjectExpression') {
        for (const operand of eachInstructionValueOperand(value)) {
          if (objectMethodDecls.has(operand.identifier)) {
            const operandScope = operand.identifier.scope;
            const lvalueScope = lvalue.identifier.scope;

            CompilerError.invariant(
              operandScope != null && lvalueScope != null,
              {
                reason:
                  'Internal error: Expected all ObjectExpressions and ObjectMethods to have non-null scope.',
                loc: GeneratedSource,
              },
            );
            mergeScopesBuilder.union([operandScope, lvalueScope]);
          }
        }
      }
    }
  }
  return mergeScopesBuilder;
}

export function alignObjectMethodScopes(fn: HIRFunction): void {
  // Handle inner functions: we assume that Scopes are disjoint across functions
  for (const [_, block] of fn.body.blocks) {
    for (const {value} of block.instructions) {
      if (
        value.kind === 'ObjectMethod' ||
        value.kind === 'FunctionExpression'
      ) {
        alignObjectMethodScopes(value.loweredFunc.func);
      }
    }
  }

  const scopeGroupsMap = findScopesToMerge(fn).canonicalize();
  /**
   * Step 1: Merge affected scopes to their canonical root.
   */
  for (const [scope, root] of scopeGroupsMap) {
    if (scope !== root) {
      root.range.start = makeInstructionId(
        Math.min(scope.range.start, root.range.start),
      );
      root.range.end = makeInstructionId(
        Math.max(scope.range.end, root.range.end),
      );
    }
  }

  /**
   * Step 2: Repoint identifiers whose scopes were merged.
   */
  for (const [_, block] of fn.body.blocks) {
    for (const {
      lvalue: {identifier},
    } of block.instructions) {
      if (identifier.scope != null) {
        const root = scopeGroupsMap.get(identifier.scope);
        if (root != null) {
          identifier.scope = root;
        }
        // otherwise, this identifier's scope was not affected by this pass
      }
    }
  }
}

Domain

Subdomains

Frequently Asked Questions

What does AlignObjectMethodScopes.ts do?
AlignObjectMethodScopes.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 AlignObjectMethodScopes.ts?
AlignObjectMethodScopes.ts defines 2 function(s): alignObjectMethodScopes, findScopesToMerge.
What does AlignObjectMethodScopes.ts depend on?
AlignObjectMethodScopes.ts imports 6 module(s): .., DisjointSet, DisjointSet.ts, eachInstructionValueOperand, index.ts, visitors.ts.
Where is AlignObjectMethodScopes.ts in the architecture?
AlignObjectMethodScopes.ts is located at compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/AlignObjectMethodScopes.ts (domain: BabelCompiler, subdomain: Validation, directory: compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes).

Analyze Your Own Codebase

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

Try Supermodel Free