Home / File/ aliased-nested-scope-truncated-dep.tsx — react Source File

aliased-nested-scope-truncated-dep.tsx — react Source File

Architecture documentation for aliased-nested-scope-truncated-dep.tsx, a tsx file in the react codebase. 1 imports, 0 dependents.

File tsx TestingUtilities Fixtures 1 imports 1 functions

Entity Profile

Dependency Diagram

graph LR
  b6639f9c_b1c3_c5ef_b1a0_3f3622dfd822["aliased-nested-scope-truncated-dep.tsx"]
  006eec3d_77a9_4a47_e6c1_a96d7a6c9c05["shared-runtime"]
  b6639f9c_b1c3_c5ef_b1a0_3f3622dfd822 --> 006eec3d_77a9_4a47_e6c1_a96d7a6c9c05
  style b6639f9c_b1c3_c5ef_b1a0_3f3622dfd822 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

// @enableNewMutationAliasingModel
import {
  Stringify,
  mutate,
  identity,
  shallowCopy,
  setPropertyByKey,
} from 'shared-runtime';

/**
 * This fixture is similar to `bug-aliased-capture-aliased-mutate` and
 * `nonmutating-capture-in-unsplittable-memo-block`, but with a focus on
 * dependency extraction.
 *
 * NOTE: this fixture is currently valid, but will break with optimizations:
 * - Scope and mutable-range based reordering may move the array creation
 *     *after* the `mutate(aliasedObj)` call. This is invalid if mutate
 *     reassigns inner properties.
 * - RecycleInto or other deeper-equality optimizations may produce invalid
 *     output -- it may compare the array's contents / dependencies too early.
 * - Runtime validation for immutable values will break if `mutate` does
 *     interior mutation of the value captured into the array.
 *
 * Before scope block creation, HIR looks like this:
 *  //
 *  // $1 is unscoped as obj's mutable range will be
 *  // extended in a later pass
 *  //
 *  $1    = LoadLocal obj@0[0:12]
 *  $2    = PropertyLoad $1.id
 *  //
 *  // $3 gets assigned a scope as Array is an allocating
 *  // instruction, but this does *not* get extended or
 *  // merged into the later mutation site.
 *  // (explained in `bug-aliased-capture-aliased-mutate`)
 *  //
 *  $3@1  = Array[$2]
 *  ...
 *  $10@0 = LoadLocal shallowCopy@0[0, 12]
 *  $11   = LoadGlobal mutate
 *  $12   = $11($10@0[0, 12])
 *
 * When filling in scope dependencies, we find that it's incorrect to depend on
 * PropertyLoads from obj as it hasn't completed its mutable range. Following
 * the immutable / mutable-new typing system, we check the identity of obj to
 * detect whether it was newly created (and thus mutable) in this render pass.
 *
 * HIR with scopes looks like this.
 * bb0:
 *  $1    = LoadLocal obj@0[0:12]
 *  $2    = PropertyLoad $1.id
 *  scopeTerminal deps=[obj@0] block=bb1 fallt=bb2
 * bb1:
 *  $3@1  = Array[$2]
 *  goto bb2
 * bb2:
 *  ...
 *
 * This is surprising as deps now is entirely decoupled from temporaries used
 * by the block itself. scope @1's instructions now reference a value (1)
 * produced outside its scope range and (2) not represented in its dependencies
 *
 * The right thing to do is to ensure that all Loads from a value get assigned
 * the value's reactive scope. This also requires track mutating and aliasing
 * separately from scope range. In this example, that would correctly merge
 * the scopes of $3 with obj.
 * Runtime validation and optimizations such as ReactiveGraph-based reordering
 * require this as well.
 *
 * A tempting fix is to instead extend $3's ReactiveScope range up to include
 * $2 (the PropertyLoad). This fixes dependency deduping but not reordering
 * and mutability.
 */
function Component({prop}) {
  let obj = shallowCopy(prop);
  const aliasedObj = identity(obj);

  // [obj.id] currently is assigned its own reactive scope
  const id = [obj.id];

  // Writing to the alias may reassign to previously captured references.
  // The compiler currently produces valid output, but this breaks with
  // reordering, recycleInto, and other potential optimizations.
  mutate(aliasedObj);
  setPropertyByKey(aliasedObj, 'id', prop.id + 1);

  return <Stringify id={id} />;
}

export const FIXTURE_ENTRYPOINT = {
  fn: Component,
  params: [{prop: {id: 1}}],
  sequentialRenders: [{prop: {id: 1}}, {prop: {id: 1}}, {prop: {id: 2}}],
};

Subdomains

Functions

Dependencies

  • shared-runtime

Frequently Asked Questions

What does aliased-nested-scope-truncated-dep.tsx do?
aliased-nested-scope-truncated-dep.tsx is a source file in the react codebase, written in tsx. It belongs to the TestingUtilities domain, Fixtures subdomain.
What functions are defined in aliased-nested-scope-truncated-dep.tsx?
aliased-nested-scope-truncated-dep.tsx defines 1 function(s): Component.
What does aliased-nested-scope-truncated-dep.tsx depend on?
aliased-nested-scope-truncated-dep.tsx imports 1 module(s): shared-runtime.
Where is aliased-nested-scope-truncated-dep.tsx in the architecture?
aliased-nested-scope-truncated-dep.tsx is located at compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/aliased-nested-scope-truncated-dep.tsx (domain: TestingUtilities, subdomain: Fixtures, directory: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability).

Analyze Your Own Codebase

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

Try Supermodel Free