1,147 matches across 25 files for func main lang:Markdown lang:Markdown
snippet_mode: auto · sorted by relevance
9
10- Follow patterns from `compiler/docs/rust-port/rust-port-architecture.md`
11▶- Use arenas + copyable IDs instead of shared references: `IdentifierId`, `ScopeId`, `FunctionId`, `TypeId`
12- Pass `env: &mut Environment` separately from `func: &mut HirFunction`
13- Use two-phase collect/apply when you can't mutate through stored references
· · ·
12▶- Pass `env: &mut Environment` separately from `func: &mut HirFunction`
13- Use two-phase collect/apply when you can't mutate through stored references
14- Run `bash compiler/scripts/test-babel-ast.sh` to test AST round-tripping
· · ·
19Before declaring work complete on a plan doc:
20- Re-read the original user prompt to ensure all requested steps are done
21▶- Check the plan doc for any "Remaining Work" items
22- Verify test-babel-ast.sh passes with the expected fixture count
23- Update the plan doc's status section
10
11## Input Invariants
12▶- The function has been converted to a ReactiveFunction structure
13- `InferReactivePlaces` has annotated places with `{reactive: true}` where values can change
14- Each `ReactiveScopeBlock` has a `scope.dependencies` set populated by `PropagateScopeDependenciesHIR`
· · ·
17## Output Guarantees
18- **Non-reactive dependencies removed**: All dependencies in `scope.dependencies` are reactive after this pass
19▶- **Scope outputs marked reactive if needed**: If a scope has any reactive dependencies remaining, all its outputs are marked reactive
20- **Stable types remain non-reactive through property loads**: When loading properties from stable types (like `useReducer` dispatch functions), the result is not added to the reactive set
21
· · ·
20▶- **Stable types remain non-reactive through property loads**: When loading properties from stable types (like `useReducer` dispatch functions), the result is not added to the reactive set
21
22## Algorithm
· · ·
24### Phase 1: Collect Reactive Identifiers
25The `collectReactiveIdentifiers` helper builds the initial set of reactive identifiers by:
26▶1. Visiting all places in the ReactiveFunction
272. Adding any place marked `{reactive: true}` to the set
283. For pruned scopes, adding declarations that are not primitives and not stable ref types
· · ·
29
30### Phase 2: Propagate Reactivity and Prune Dependencies
31▶The main `Visitor` class traverses the ReactiveFunction and:
32
331. **For Instructions** - Propagates reactivity through data flow:
+ 6 more matches in this file
4* Define a Scope type that encodes the tree of scope information, mapping to the information that babel represents in its own scope tree
5
6▶The main public API is roughly `compile(BabelAst, Scope) -> Option<BabelAst>` returning None if no changes, or Some with the updated ast.
7
8## Arenas
· · ·
16 * Table on Environment, stores actual ReactiveScope values
17 * `Identifier`, scope terminals, etc reference indirectly via `ScopeID`
18▶* `Function`:
19 * Table on Environment, stores the inner HirFunction values
20 * `InstructionValue::FunctionExpression` and `::ObjectMethod` reference indirectly via `FunctionId`
· · ·
19▶ * Table on Environment, stores the inner HirFunction values
20 * `InstructionValue::FunctionExpression` and `::ObjectMethod` reference indirectly via `FunctionId`
21* `Type`:
· · ·
20▶ * `InstructionValue::FunctionExpression` and `::ObjectMethod` reference indirectly via `FunctionId`
21* `Type`:
22 * Table on Environment, stores actual types
· · ·
28
29* Rename `InstructionId` to `EvaluationOrder` - this type is actually about representing the evaluation order, and is not even instruction-specific: it is also present on terminals.
30▶* `HirFunction` stores `instructions: Vec<InstructionId>`
31* `BasicBlock.instructions` becomes `Vec<InstructionId>`, indexing into the `HirFunction.instructions` vec
32
+ 7 more matches in this file
5
6## Purpose
7▶This pass builds an abstract model of the heap and interprets the effects of the given function to determine: (1) the mutable ranges of all identifiers, (2) the externally-visible effects of the function (mutations of params/context-vars, aliasing relationships), and (3) the legacy `Effect` annotation for each Place.
8
9## Input Invariants
· · ·
11- SSA form must be established (identifiers are in SSA)
12- Type inference has been run (InferTypes)
13▶- Functions have been analyzed (AnalyseFunctions)
14- Dead code elimination has been performed
15
· · ·
17- Every identifier has a populated `mutableRange` (start:end instruction IDs)
18- Every Place has a legacy `Effect` annotation (Read, Capture, Store, Freeze, etc.)
19▶- The function's `aliasingEffects` array is populated with externally-visible effects (mutations of params/context-vars, aliasing between params/context-vars/return)
20- Validation errors are collected for invalid effects like `MutateFrozen` or `MutateGlobal`
21
· · ·
22## Algorithm
23▶The pass operates in three main phases:
24
25**Part 1: Build Data Flow Graph and Infer Mutable Ranges**
· · ·
26▶1. Creates an `AliasingState` which maintains a `Node` for each identifier
272. Iterates through all blocks and instructions, processing effects in program order
283. For each effect:
+ 11 more matches in this file
12- SSA form: Each identifier has a unique `IdentifierId` and `DeclarationId`
13- Dead code elimination has run: Unused assignments have been removed
14▶- Mutation/aliasing inference complete: Runs after `InferMutationAliasingRanges` and `InferReactivePlaces` in the main pipeline
15- All instruction kinds are initially set (typically `Let` for variables that may be reassigned)
16
· · ·
271. **Initialize declarations map**: Create a `Map<DeclarationId, LValue | LValuePattern>` to track declared variables.
28
29▶2. **Seed with parameters and context**: Add all named function parameters and captured context variables to the map with kind `Let` (since they're already "declared" outside the function body).
30
313. **Process blocks in order**: Iterate through all blocks and instructions:
· · ·
47
48```typescript
49▶// Main tracking structure
50const declarations = new Map<DeclarationId, LValue | LValuePattern>();
51
· · ·
58 HoistedLet = 'HoistedLet', // hoisted let
59 HoistedConst = 'HoistedConst', // hoisted const
60▶ HoistedFunction = 'HoistedFunction', // hoisted function
61 Function = 'Function', // function declaration
62}
· · ·
61▶ Function = 'Function', // function declaration
62}
63```
+ 5 more matches in this file
5
6## Purpose
7▶Infers types for all identifiers in the HIR by generating type equations and solving them using unification. This pass annotates identifiers with concrete types (Primitive, Object, Function) based on the operations performed on them and the types of globals/hooks they interact with.
8
9## Input Invariants
· · ·
15- All identifier types are resolved from type variables (`Type`) to concrete types where possible
16- Phi nodes have their operand types unified to produce a single result type
17▶- Function return types are inferred from the unified types of all return statements
18- Property accesses on known objects/hooks resolve to the declared property types
19- Component props parameters are typed as `TObject<BuiltInProps>`
· · ·
251. **Constraint Generation (`generate`)**: Traverses all instructions and generates type equations:
26 - Primitives, literals, unary/binary operations -> `Primitive` type
27▶ - Hook/function calls -> Function type with fresh return type variable
28 - Property loads -> `Property` type that defers to object shape lookup
29 - Destructuring -> Property types for each extracted element
· · ·
37 - Property types are resolved by looking up the object's shape
38 - Phi types are resolved by finding a common type among operands (or falling back to `Phi` if incompatible)
39▶ - Function types are unified by unifying their return types
40 - Occurs check prevents infinite types (cycles in type references)
41
· · ·
44## Key Data Structures
45- **TypeVar** (`kind: 'Type'`): A type variable with a unique TypeId, used for unknowns
46▶- **Unifier**: Maintains a substitution map from TypeId to Type, with methods for unification and cycle detection
47- **TypeEquation**: A pair of types that should be equal, used as constraints
48- **PhiType** (`kind: 'Phi'`): Represents the join of multiple types from control flow merge points
+ 8 more matches in this file
20- Unreachable blocks are removed and the CFG is minimized
21- Phi nodes with unreachable predecessor operands are pruned
22▶- Nested functions (`FunctionExpression`, `ObjectMethod`) are recursively processed
23
24## Algorithm
· · ·
63- **Division results**: Computed at compile time (may produce `NaN`, `Infinity`, etc.)
64- **LoadGlobal in phis**: Only propagated if all operands reference the same global name
65▶- **Nested functions**: Constants from outer scope are propagated into nested function expressions
66
67## TODOs
· · ·
72**Input:**
73```javascript
74▶function Component() {
75 let a = 1;
76
· · ·
95**After ConstantPropagation:**
96- `a === 1` evaluates to `true`
97▶- The `if (a === 1)` branch is eliminated, only consequent remains
98- `b` is known to be `true`
99- `if (b)` branch is eliminated, only consequent remains
· · ·
99▶- `if (b)` branch is eliminated, only consequent remains
100- `c` is known to be `'hello'`
101- All intermediate blocks are merged
+ 1 more matches in this file
17
18### Option 1 (fastest): Checkout pre-built React
19▶To check out the latest version of React (built by CI from the `main` branch) run:
20```sh
21cd <react-repo>
· · ·
24yarn install
25
26▶./download-experimental-build.js --commit=main
27```
28
· · ·
66
67# Unit tests
68▶Core DevTools functionality is typically unit tested (see [here](https://github.com/facebook/react/tree/main/packages/react-devtools-shared/src/__tests__)). To run tests, you'll first need to build or download React and React DOM ([as explained above](#build-react-and-react-dom)) and then use the following NPM script:
69```sh
70yarn test-build-devtools
· · ·
76
77# Finding the right first issue
78▶The React team maintains [this list of "good first issues"](https://github.com/facebook/react/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Component%3A+Developer+Tools%22+label%3A%22good+first+issue%22) for anyone interested in contributing to DevTools. If you see one that interests you, leave a comment!
79
80If you have ideas or suggestions of your own, you can also put together a PR demonstrating them. We suggest filing an issue before making any substantial changes though, to ensure that the idea is something the team feels comfortable landing.
7When modifying the compiler, you MUST read the documentation about that pass in `compiler/packages/babel-plugin-react-compiler/docs/passes/` to learn more about the role of that pass within the compiler.
8
9▶- `packages/babel-plugin-react-compiler/` - Main compiler package
10 - `src/HIR/` - High-level Intermediate Representation types and utilities
11 - `src/Inference/` - Effect inference passes (aliasing, mutation, etc.)
· · ·
12 - `src/Validation/` - Validation passes that check for errors
13▶ - `src/Entrypoint/Pipeline.ts` - Main compilation pipeline with pass ordering
14 - `src/__tests__/fixtures/compiler/` - Test fixtures
15 - `error.todo-*.js` - Unsupported feature, correctly throws Todo error (graceful bailout)
· · ·
104The compiler converts source code to HIR for analysis. Key types in `src/HIR/HIR.ts`:
105
106▶- **HIRFunction** - A function being compiled
107 - `body.blocks` - Map of BasicBlocks
108 - `context` - Captured variables from outer scope
· · ·
109▶ - `params` - Function parameters
110 - `returns` - The function's return place
111 - `aliasingEffects` - Effects that describe the function's behavior when called
· · ·
110▶ - `returns` - The function's return place
111 - `aliasingEffects` - Effects that describe the function's behavior when called
112
+ 14 more matches in this file
10
11## Input Invariants
12▶- The function has been through type inference
13- FBT calls (`fbt`, `fbt.c`, `fbt:param`, etc.) are properly identified
14- Custom macros are configured in `fn.env.config.customMacros`
· · ·
17## Output Guarantees
18- All operands of FBT calls are assigned to the same reactive scope as the FBT call
19▶- The `fbtOperands` set is returned for use by other passes (e.g., `outlineFunctions`)
20- Operand scope assignments use either transitive or shallow inlining based on macro definition
21
· · ·
32### Phase 2: Populate Macro Tags
33```typescript
34▶function populateMacroTags(
35 fn: HIRFunction,
36 macroKinds: Map<Macro, MacroDefinition>,
· · ·
35▶ fn: HIRFunction,
36 macroKinds: Map<Macro, MacroDefinition>,
37): Map<IdentifierId, MacroDefinition> {
· · ·
53### Phase 3: Merge Macro Arguments
54```typescript
55▶function mergeMacroArguments(
56 fn: HIRFunction,
57 macroTags: Map<IdentifierId, MacroDefinition>,
+ 5 more matches in this file
21snapshot at top.)
22
23▶The 15 remaining SWC e2e failures fall into three groups. Each line names the
24fixture and the failure mode; the group it sits in dictates the appropriate
25fix.
· · ·
26
27▶### Group A: Fixture maintenance, not Rust bugs
28
29SWC compiles code that TS rejects, or vice versa, in ways where Rust's
· · ·
39 emits a Todo bailout (`[hoisting] EnterSSA: Expected identifier to be
40 defined before being used`) that the Babel path does not.
41▶- `error.todo-repro-named-function-with-shadowed-local-same-name.js` —
42 Babel errors; SWC compiles.
43- `new-mutability/error.todo-repro-named-function-with-shadowed-local-same-name.js`
· · ·
43▶- `new-mutability/error.todo-repro-named-function-with-shadowed-local-same-name.js`
44 — same as above with the new mutation-aliasing model enabled.
45- `error.todo-rust-as-expression-assignment-target.tsx` — Babel errors;
· · ·
53
54- `use-no-forget-multiple-with-eslint-suppression.js` — spurious
55▶ `import { c as _c }` in the TS reference output. Fixed on `main` by
56 [react#36500](https://github.com/facebook/react/pull/36500) (merged).
57 Will pass automatically once `pr-36173` rebases onto `main`; until then
+ 6 more matches in this file
10- The HIR must have blocks in reverse postorder (predecessors visited before successors, except for back-edges)
11- Block predecessor information (`block.preds`) must be populated correctly
12▶- The function's `context` array must be empty for the root function (outer function declarations)
13- Identifiers may be reused across multiple definitions/assignments (non-SSA form)
14
· · ·
17- All operand references use the SSA-renamed identifiers
18- Phi nodes are inserted at join points where values from different control flow paths converge
19▶- Function parameters are SSA-renamed
20- Nested functions (FunctionExpression, ObjectMethod) are recursively converted to SSA form
21- Context variables (captured from outer scopes) are handled specially and not redefined
· · ·
20▶- Nested functions (FunctionExpression, ObjectMethod) are recursively converted to SSA form
21- Context variables (captured from outer scopes) are handled specially and not redefined
22
· · ·
23## Algorithm
24▶The pass uses the Braun et al. algorithm ("Simple and Efficient Construction of Static Single Assignment Form") with adaptations for handling loops and nested functions.
25
26### Key Steps:
· · ·
271. **Block Traversal**: Iterate through blocks in order (assumed reverse postorder from previous passes)
28▶2. **Definition Tracking**: Maintain a per-block `defs` map from original identifiers to their SSA-renamed versions
293. **Renaming**:
30 - When a value is **defined** (lvalue), create a new SSA identifier with fresh `IdentifierId`
+ 6 more matches in this file
5
6## Purpose
7▶The `propagateScopeDependenciesHIR` pass is responsible for computing and assigning the **dependencies** for each reactive scope in the compiled function. Dependencies are the external values that a scope reads, which determine when the scope needs to re-execute. This is a critical step for memoization correctness - the compiler must track exactly which values a scope depends on so it can generate proper cache invalidation checks.
8
9The pass also populates:
· · ·
13## Input Invariants
14- Reactive scopes must be established (pass runs after `BuildReactiveScopeTerminalsHIR`)
15▶- The function must be in SSA form
16- `InferMutationAliasingRanges` must have run to establish when values are being mutated
17- `InferReactivePlaces` marks which identifiers are reactive
· · ·
54### Phase 2: Collect Dependencies
55
56▶The `collectDependencies` function traverses the HIR, maintaining a stack of active scopes:
57
581. **Scope Entry/Exit**: When entering a scope terminal, push a new dependency array. When exiting, propagate collected dependencies to parent scopes if valid.
· · ·
96
97### DependencyCollectionContext
98▶Maintains:
99- `#declarations`: Map of DeclarationId to {id, scope} recording where each value was declared
100- `#reassignments`: Map of Identifier to latest assignment info
· · ·
117Optional chains like `a?.b?.c` produce different dependency paths than `a.b.c`. The pass distinguishes them and may merge optional loads into unconditional ones when control flow proves the object is non-null.
118
119▶### Inner Functions
120Dependencies from inner functions are collected recursively but with special handling for context variables.
121
+ 2 more matches in this file
20| 2 | PruneMaybeThrows | hir | Validation: validateContextVariableLValues, validateUseMemo after |
21| 3 | DropManualMemoization | hir | Conditional |
22▶| 4 | InlineImmediatelyInvokedFunctionExpressions | hir | |
23| 5 | MergeConsecutiveBlocks | hir | |
24| 6 | SSA | hir | |
· · ·
27| 9 | InferTypes | hir | Validation: validateHooksUsage, validateNoCapitalizedCalls after (conditional) |
28| 10 | OptimizePropsMethodCalls | hir | |
29▶| 11 | AnalyseFunctions | hir | |
30| 12 | InferMutationAliasingEffects | hir | |
31| 13 | OptimizeForSSR | hir | Conditional: outputMode === 'ssr' |
· · ·
38| 20 | MemoizeFbtAndMacroOperandsInSameScope | hir | |
39| -- | outlineJSX | hir | Between #20 and #21, conditional: enableJsxOutlining, no log entry |
40▶| 21 | NameAnonymousFunctions | hir | Conditional |
41| 22 | OutlineFunctions | hir | Conditional |
42| 23 | AlignMethodCallScopes | hir | |
· · ·
41▶| 22 | OutlineFunctions | hir | Conditional |
42| 23 | AlignMethodCallScopes | hir | |
43| 24 | AlignObjectMethodScopes | hir | |
· · ·
49| 30 | FlattenScopesWithHooksOrUseHIR | hir | |
50| 31 | PropagateScopeDependenciesHIR | hir | |
51▶| 32 | BuildReactiveFunction | reactive | |
52| 33 | AssertWellFormedBreakTargets | debug | Validation |
53| 34 | PruneUnusedLabels | reactive | |
+ 12 more matches in this file
7This pass prunes (removes) reactive scopes whose outputs do not "escape" the component and therefore do not need to be memoized. A value "escapes" in two ways:
8
9▶1. **Returned from the function** - The value is directly returned or transitively aliased by a return value
102. **Passed to a hook** - Any value passed as an argument to a hook may be stored by React internally (e.g., the closure passed to `useEffect`)
11
· · ·
13
14## Input Invariants
15▶- The input is a `ReactiveFunction` after scope blocks have been identified
16- Reactive scopes have been assigned to instructions
17- The pass runs after `BuildReactiveFunction` and `PruneUnusedLabels`, before `PruneNonReactiveDependencies`
· · ·
17▶- The pass runs after `BuildReactiveFunction` and `PruneUnusedLabels`, before `PruneNonReactiveDependencies`
18
19## Output Guarantees
· · ·
20▶- **Scopes with non-escaping outputs are removed** - Their instructions are inlined back into the parent scope/function body
21- **Scopes with escaping outputs are retained** - Values that escape via return or hook arguments remain memoized
22- **Transitive dependencies of escaping scopes are preserved** - If an escaping scope depends on a non-escaping value, that value's scope is also retained to prevent unnecessary invalidation
· · ·
21▶- **Scopes with escaping outputs are retained** - Values that escape via return or hook arguments remain memoized
22- **Transitive dependencies of escaping scopes are preserved** - If an escaping scope depends on a non-escaping value, that value's scope is also retained to prevent unnecessary invalidation
23- **`FinishMemoize` instructions are marked `pruned=true`** - When a scope is pruned, the associated memoization instructions are flagged
+ 5 more matches in this file
3This package can be used to embed React DevTools into browser-based tools like [CodeSandbox](https://codesandbox.io/), [StackBlitz](https://stackblitz.com/), and [Replay](https://replay.io).
4
5▶If you're looking for the standalone React DevTools UI, **we suggest using [`react-devtools`](https://github.com/facebook/react/tree/main/packages/react-devtools) instead of using this package directly**.
6
7---
· · ·
13# Usage
14
15▶This package exports two entry points: a frontend (to be run in the main `window`) and a backend (to be installed and run within an `iframe`<sup>1</sup>).
16
17The frontend and backend can be initialized in any order, but **the backend must not be activated until the frontend initialization has completed**. Because of this, the simplest sequence is:
· · ·
18
19▶1. Frontend (DevTools interface) initialized in the main `window`.
201. Backend initialized in an `iframe`.
211. Backend activated.
· · ·
77DevTools can display hook "names" for an inspected component, although determining the "names" requires loading the source (and source-maps), parsing the code, and inferring the names based on which variables hook values get assigned to. Because the code for this is non-trivial, it's lazy-loaded only if the feature is enabled.
78
79▶To configure this package to support this functionality, you'll need to provide a prop that dynamically imports the extra functionality:
80```js
81// Follow code examples above to configure the backend and frontend.
· · ·
82▶// When rendering DevTools, the important part is to pass a 'hookNamesModuleLoaderFunction' prop.
83const hookNamesModuleLoaderFunction = () => import('react-devtools-inline/hookNames');
84
+ 7 more matches in this file
10
11## Input Invariants
12▶- Operates on HIRFunction (pre-reactive scope inference)
13- Effect hooks must be identified (`isUseEffectHookType`)
14- setState functions must be identified (`isSetStateType`)
· · ·
14▶- setState functions must be identified (`isSetStateType`)
15
16## Validation Rules
· · ·
17The pass detects when an effect:
181. Has a dependency array (2nd argument)
19▶2. The effect function only captures the dependencies and setState functions
203. The effect calls setState with a value derived solely from the dependencies
214. The effect has no control flow (loops with back edges)
· · ·
291. **Collection Phase**: Traverse all instructions to collect:
30 - `candidateDependencies`: Map of ArrayExpression identifiers (potential deps arrays)
31▶ - `functions`: Map of FunctionExpression identifiers (potential effect callbacks)
32 - `locals`: Map of LoadLocal sources for identifier resolution
33
· · ·
342. **Detection Phase**: When a `useEffect` call is found with 2 arguments:
35▶ - Look up the effect function and dependencies array
36 - Verify all dependency array elements are identifiers
37 - Call `validateEffect()` on the effect function
+ 4 more matches in this file
7This validation pass prevents a category of bugs where a closure captures a binding from one render but does not update when the binding is reassigned in a later render.
8
9▶When the React Compiler memoizes a function, that function captures bindings at the time of creation. If the function is reused across renders (because its dependencies haven't changed), any reassignments to captured variables will affect the wrong binding version. This can cause inconsistent behavior that's difficult to debug.
10
11The pass detects when:
· · ·
12▶1. A local variable is reassigned within a function expression
132. That function expression escapes (e.g., passed to useEffect, used as event handler)
143. The reassignment would occur after render completes (in effects or async callbacks)
· · ·
13▶2. That function expression escapes (e.g., passed to useEffect, used as event handler)
143. The reassignment would occur after render completes (in effects or async callbacks)
15
· · ·
16## Input Invariants
17▶- The function has been lowered to HIR
18- Effects have been inferred for all operands (`operand.effect !== Effect.Unknown`)
19- Function signatures have been analyzed for `noAlias` properties
· · ·
19▶- Function signatures have been analyzed for `noAlias` properties
20
21## Validation Rules
+ 57 more matches in this file
34 `04-constantPropagation.md`, `05-deadCodeElimination.md`, `06-inferTypes.md`
35
36▶3. **Function & Effect Analysis** (passes 07-09):
37 `07-analyseFunctions.md`, `08-inferMutationAliasingEffects.md`, `09-inferMutationAliasingRanges.md`
38
· · ·
37▶ `07-analyseFunctions.md`, `08-inferMutationAliasingEffects.md`, `09-inferMutationAliasingRanges.md`
38
394. **Reactivity & Scope Variables** (passes 10-14):
· · ·
43 `15-alignReactiveScopesToBlockScopesHIR.md`, `16-mergeOverlappingReactiveScopesHIR.md`, `17-buildReactiveScopeTerminalsHIR.md`, `18-flattenReactiveLoopsHIR.md`, `19-flattenScopesWithHooksOrUseHIR.md`, `20-propagateScopeDependenciesHIR.md`
44
45▶6. **Reactive Function & Transforms** (passes 21-30):
46 `21-buildReactiveFunction.md`, `22-pruneUnusedLabels.md`, `23-pruneNonEscapingScopes.md`, `24-pruneNonReactiveDependencies.md`, `25-pruneUnusedScopes.md`, `26-mergeReactiveScopesThatInvalidateTogether.md`, `27-pruneAlwaysInvalidatingScopes.md`, `28-propagateEarlyReturns.md`, `29-promoteUsedTemporaries.md`, `30-renameVariables.md`
47
· · ·
46▶ `21-buildReactiveFunction.md`, `22-pruneUnusedLabels.md`, `23-pruneNonEscapingScopes.md`, `24-pruneNonReactiveDependencies.md`, `25-pruneUnusedScopes.md`, `26-mergeReactiveScopesThatInvalidateTogether.md`, `27-pruneAlwaysInvalidatingScopes.md`, `28-propagateEarlyReturns.md`, `29-promoteUsedTemporaries.md`, `30-renameVariables.md`
47
487. **Codegen & Optimization** (passes 31, 34-38):
· · ·
49▶ `31-codegenReactiveFunction.md`, `34-optimizePropsMethodCalls.md`, `35-optimizeForSSR.md`, `36-outlineJSX.md`, `37-outlineFunctions.md`, `38-memoizeFbtAndMacroOperandsInSameScope.md`
50
518. **Validation Passes** (passes 39-55):
+ 2 more matches in this file
8
9## Input Invariants
10▶- The input is a `ReactiveFunction` that has already been transformed into reactive scope form
11- Scopes have been created and have `declarations`, `reassignments`, and potentially `earlyReturnValue` populated
12- The pass is called after:
· · ·
29## Algorithm
30
31▶The pass uses the visitor pattern with `ReactiveFunctionTransform`:
32
331. **State Tracking**: A `State` object tracks whether a return statement was encountered:
· · ·
76**Input:**
77```javascript
78▶function Component(props) {
79 const x = [];
80 useHook();
· · ·
92**Output (no memoization for x):**
93```javascript
94▶function Component(props) {
95 const x = [];
96 useHook();
· · ·
1072. `pruneNonEscapingScopes` - Prunes scopes whose outputs don't escape
1083. `pruneNonReactiveDependencies` - Removes non-reactive dependencies
109▶4. **`pruneUnusedScopes`** - Prunes scopes with no remaining outputs
110
111This pass acts as a cleanup for scopes that became "empty" after previous pruning passes removed their outputs.
10
11## Input Invariants
12▶- Operates on HIRFunction (pre-reactive scope inference)
13- Effect hooks must be identified (`isUseEffectHookType`, `isUseLayoutEffectHookType`, `isUseInsertionEffectHookType`)
14- setState functions must be identified (`isSetStateType`)
· · ·
14▶- setState functions must be identified (`isSetStateType`)
15- Only runs when `outputMode === 'lint'`
16
· · ·
24Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:
25* Update external systems with the latest state from React.
26▶* Subscribe for updates from some external system, calling setState in a callback function when external state changes.
27
28Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended.
· · ·
33
34## Algorithm
35▶1. **Main function traversal**: Build a map `setStateFunctions` tracking which identifiers are setState functions
362. For each instruction:
37 - **LoadLocal/StoreLocal**: Propagate setState tracking through variable assignments
· · ·
38▶ - **FunctionExpression**: Check if the function synchronously calls setState by recursively calling `getSetStateCall()`. If so, track the function as a setState-calling function
39 - **useEffectEvent call**: If the argument is a function that calls setState, track the return value as a setState function
40 - **useEffect/useLayoutEffect/useInsertionEffect call**: Check if the callback argument is tracked as calling setState. If so, emit an error
+ 6 more matches in this file
5
6## Purpose
7▶This is the **2nd of 4 passes** that determine how to break a function into discrete reactive scopes (independently memoizable units of code). The pass aligns reactive scope boundaries to control flow (block scope) boundaries.
8
9The problem it solves: Prior inference passes assign reactive scopes to operands based on mutation ranges at arbitrary instruction points in the control-flow graph. However, to generate memoization blocks around instructions, scopes must be aligned to block-scope boundaries -- you cannot memoize half of a loop or half of an if-block.
· · ·
11**Example from the source code comments:**
12```javascript
13▶function foo(cond, a) {
14 // original scope end
15 // expanded scope end
· · ·
39
40### 1. Tracking Active Scopes
41▶- Maintains `activeScopes: Set<ReactiveScope>` - scopes whose range overlaps the current block
42- Maintains `activeBlockFallthroughRanges: Array<{range, fallthrough}>` - stack of pending block-fallthrough ranges
43
· · ·
42▶- Maintains `activeBlockFallthroughRanges: Array<{range, fallthrough}>` - stack of pending block-fallthrough ranges
43
44### 2. Per-Block Processing
· · ·
117**Input:**
118```javascript
119▶function foo(a, b, c) {
120 let x = [];
121 if (a) {
+ 1 more matches in this file
16InferTypes: complete
17OptimizePropsMethodCalls: complete
18▶AnalyseFunctions: complete (1649/1649)
19InferMutationAliasingEffects: complete (1643/1643)
20OptimizeForSSR: complete (5/5, conditional, outputMode === 'ssr')
· · ·
27MemoizeFbtAndMacroOperandsInSameScope: complete
28outlineJSX: complete (conditional on enableJsxOutlining)
29▶NameAnonymousFunctions: complete (2/2, conditional)
30OutlineFunctions: complete
31AlignMethodCallScopes: complete
· · ·
30▶OutlineFunctions: complete
31AlignMethodCallScopes: complete
32AlignObjectMethodScopes: complete
· · ·
38FlattenScopesWithHooksOrUseHIR: complete
39PropagateScopeDependenciesHIR: complete
40▶BuildReactiveFunction: complete
41AssertWellFormedBreakTargets: complete
42PruneUnusedLabels: complete
· · ·
66Program.ts logged directive as [object Object] instead of its string value.
67(2) Rust program.rs used inferred fn_name for CompileSuccess instead of
68▶codegen_fn.id, causing arrow functions to report names the TS compiler doesn't.
69Removed all code output normalization from test-e2e.ts — comparison now uses
70prettier only.
+ 125 more matches in this file
5
6## Purpose
7▶This pass ensures that every named variable in the function has a unique name that doesn't conflict with other variables in the same block scope or with global identifiers. After scope construction and temporary promotion, variables from different source scopes may end up in the same reactive block - this pass resolves any naming conflicts.
8
9The pass also converts the `#t{id}` promoted temporary names into clean output names like `t0`, `t1`, etc.
· · ·
10
11## Input Invariants
12▶- The ReactiveFunction has been through `promoteUsedTemporaries`
13- Variables may have names that conflict with:
14 - Other variables in the same or ancestor block scope
· · ·
15▶ - Global identifiers referenced by the function
16 - Promoted temporaries with `#t{id}` or `#T{id}` naming
17- The function parameters have names (either from source or promoted)
· · ·
17▶- The function parameters have names (either from source or promoted)
18
19## Output Guarantees
· · ·
20- Every named variable has a unique name within its scope
21▶- No variable shadows a global identifier referenced by the function
22- Promoted temporaries are renamed to `t0`, `t1`, ... (for regular temps)
23- Promoted JSX temporaries are renamed to `T0`, `T1`, ... (for JSX tags)
+ 9 more matches in this file
10
11## Input Invariants
12▶- Operates on HIRFunction (pre-reactive scope inference)
13- Blocks are traversed in order
14- Only runs when `outputMode === 'lint'`
· · ·
30
31## Algorithm
32▶1. Maintain a stack `activeTryBlocks` of currently active try statement handler block IDs
332. For each block:
34 - Remove the current block from `activeTryBlocks` if it matches a handler (we've exited the try scope)
· · ·
46```javascript
47// Valid - catch block is not inside a try
48▶function Component() {
49 try {
50 doSomething();
· · ·
58```javascript
59// Error - catch is inside outer try
60▶function Component() {
61 try {
62 try {
· · ·
74```javascript
75// Error - JSX creation is in try block
76▶function Component() {
77 let el;
78 try {
+ 2 more matches in this file