mirror of
https://github.com/facebook/react.git
synced 2026-02-22 03:42:05 +00:00
[compiler] Claude file/settings (#35523)
Initializes CLAUDE.md and a settings file for the compiler/ directory to help use claude with the compiler. Note that some of the commands here depend on changes to snap from the next PR. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35523). * #35607 * #35298 * #35596 * #35573 * #35595 * #35539 * #35537 * __->__ #35523
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(yarn snap:*)",
|
||||
"Bash(yarn snap:build)",
|
||||
"Bash(node scripts/enable-feature-flag.js:*)"
|
||||
],
|
||||
"deny": [],
|
||||
2
compiler/.gitignore
vendored
2
compiler/.gitignore
vendored
@@ -8,7 +8,9 @@ dist
|
||||
.vscode
|
||||
!packages/playground/.vscode
|
||||
testfilter.txt
|
||||
.claude/settings.local.json
|
||||
|
||||
# forgive
|
||||
*.vsix
|
||||
.vscode-test
|
||||
|
||||
|
||||
221
compiler/CLAUDE.md
Normal file
221
compiler/CLAUDE.md
Normal file
@@ -0,0 +1,221 @@
|
||||
# React Compiler Knowledge Base
|
||||
|
||||
This document contains knowledge about the React Compiler gathered during development sessions. It serves as a reference for understanding the codebase architecture and key concepts.
|
||||
|
||||
## Project Structure
|
||||
|
||||
- `packages/babel-plugin-react-compiler/` - Main compiler package
|
||||
- `src/HIR/` - High-level Intermediate Representation types and utilities
|
||||
- `src/Inference/` - Effect inference passes (aliasing, mutation, etc.)
|
||||
- `src/Validation/` - Validation passes that check for errors
|
||||
- `src/Entrypoint/Pipeline.ts` - Main compilation pipeline with pass ordering
|
||||
- `src/__tests__/fixtures/compiler/` - Test fixtures
|
||||
- `error.todo-*.js` - Unsupported feature, correctly throws Todo error (graceful bailout)
|
||||
- `error.bug-*.js` - Known bug, throws wrong error type or incorrect behavior
|
||||
- `*.expect.md` - Expected output for each fixture
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
yarn snap
|
||||
|
||||
# Run tests matching a pattern
|
||||
# Example: yarn snap -p 'error.*'
|
||||
yarn snap -p <pattern>
|
||||
|
||||
# Run a single fixture in debug mode. Use the path relative to the __tests__/fixtures/compiler directory
|
||||
# For each step of compilation, outputs the step name and state of the compiled program
|
||||
# Example: yarn snap -p simple.js -d
|
||||
yarn snap -p <file-basename> -d
|
||||
|
||||
# Update fixture outputs (also works with -p)
|
||||
yarn snap -u
|
||||
```
|
||||
|
||||
## Version Control
|
||||
|
||||
This repository uses Sapling (`sl`) for version control. Sapling is similar to Mercurial: there is not staging area, but new/deleted files must be explicitlyu added/removed.
|
||||
|
||||
```bash
|
||||
# Check status
|
||||
sl status
|
||||
|
||||
# Add new files, remove deleted files
|
||||
sl addremove
|
||||
|
||||
# Commit all changes
|
||||
sl commit -m "Your commit message"
|
||||
|
||||
# Commit with multi-line message using heredoc
|
||||
sl commit -m "$(cat <<'EOF'
|
||||
Summary line
|
||||
|
||||
Detailed description here
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### HIR (High-level Intermediate Representation)
|
||||
|
||||
The compiler converts source code to HIR for analysis. Key types in `src/HIR/HIR.ts`:
|
||||
|
||||
- **HIRFunction** - A function being compiled
|
||||
- `body.blocks` - Map of BasicBlocks
|
||||
- `context` - Captured variables from outer scope
|
||||
- `params` - Function parameters
|
||||
- `returns` - The function's return place
|
||||
- `aliasingEffects` - Effects that describe the function's behavior when called
|
||||
|
||||
- **Instruction** - A single operation
|
||||
- `lvalue` - The place being assigned to
|
||||
- `value` - The instruction kind (CallExpression, FunctionExpression, LoadLocal, etc.)
|
||||
- `effects` - Array of AliasingEffects for this instruction
|
||||
|
||||
- **Terminal** - Block terminators (return, branch, etc.)
|
||||
- `effects` - Array of AliasingEffects
|
||||
|
||||
- **Place** - A reference to a value
|
||||
- `identifier.id` - Unique IdentifierId
|
||||
|
||||
- **Phi nodes** - Join points for values from different control flow paths
|
||||
- Located at `block.phis`
|
||||
- `phi.place` - The result place
|
||||
- `phi.operands` - Map of predecessor block to source place
|
||||
|
||||
### AliasingEffects System
|
||||
|
||||
Effects describe data flow and operations. Defined in `src/Inference/AliasingEffects.ts`:
|
||||
|
||||
**Data Flow Effects:**
|
||||
- `Impure` - Marks a place as containing an impure value (e.g., Date.now() result, ref.current)
|
||||
- `Capture a -> b` - Value from `a` is captured into `b` (mutable capture)
|
||||
- `Alias a -> b` - `b` aliases `a`
|
||||
- `ImmutableCapture a -> b` - Immutable capture (like Capture but read-only)
|
||||
- `Assign a -> b` - Direct assignment
|
||||
- `MaybeAlias a -> b` - Possible aliasing
|
||||
- `CreateFrom a -> b` - Created from source
|
||||
|
||||
**Mutation Effects:**
|
||||
- `Mutate value` - Value is mutated
|
||||
- `MutateTransitive value` - Value and transitive captures are mutated
|
||||
- `MutateConditionally value` - May mutate
|
||||
- `MutateTransitiveConditionally value` - May mutate transitively
|
||||
|
||||
**Other Effects:**
|
||||
- `Render place` - Place is used in render context (JSX props, component return)
|
||||
- `Freeze place` - Place is frozen (made immutable)
|
||||
- `Create place` - New value created
|
||||
- `CreateFunction` - Function expression created, includes `captures` array
|
||||
- `Apply` - Function application with receiver, function, args, and result
|
||||
|
||||
### Hook Aliasing Signatures
|
||||
|
||||
Located in `src/HIR/Globals.ts`, hooks can define custom aliasing signatures to control how data flows through them.
|
||||
|
||||
**Structure:**
|
||||
```typescript
|
||||
aliasing: {
|
||||
receiver: '@receiver', // The hook function itself
|
||||
params: ['@param0'], // Named positional parameters
|
||||
rest: '@rest', // Rest parameters (or null)
|
||||
returns: '@returns', // Return value
|
||||
temporaries: [], // Temporary values during execution
|
||||
effects: [ // Array of effects to apply when hook is called
|
||||
{kind: 'Freeze', value: '@param0', reason: ValueReason.HookCaptured},
|
||||
{kind: 'Assign', from: '@param0', into: '@returns'},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
**Common patterns:**
|
||||
|
||||
1. **RenderHookAliasing** (useState, useContext, useMemo, useCallback):
|
||||
- Freezes arguments (`Freeze @rest`)
|
||||
- Marks arguments as render-time (`Render @rest`)
|
||||
- Creates frozen return value
|
||||
- Aliases arguments to return
|
||||
|
||||
2. **EffectHookAliasing** (useEffect, useLayoutEffect, useInsertionEffect):
|
||||
- Freezes function and deps
|
||||
- Creates internal effect object
|
||||
- Captures function and deps into effect
|
||||
- Returns undefined
|
||||
|
||||
3. **Event handler hooks** (useEffectEvent):
|
||||
- Freezes callback (`Freeze @fn`)
|
||||
- Aliases input to return (`Assign @fn -> @returns`)
|
||||
- NO Render effect (callback not called during render)
|
||||
|
||||
**Example: useEffectEvent**
|
||||
```typescript
|
||||
const UseEffectEventHook = addHook(
|
||||
DEFAULT_SHAPES,
|
||||
{
|
||||
positionalParams: [Effect.Freeze], // Takes one positional param
|
||||
restParam: null,
|
||||
returnType: {kind: 'Function', ...},
|
||||
calleeEffect: Effect.Read,
|
||||
hookKind: 'useEffectEvent',
|
||||
returnValueKind: ValueKind.Frozen,
|
||||
aliasing: {
|
||||
receiver: '@receiver',
|
||||
params: ['@fn'], // Name for the callback parameter
|
||||
rest: null,
|
||||
returns: '@returns',
|
||||
temporaries: [],
|
||||
effects: [
|
||||
{kind: 'Freeze', value: '@fn', reason: ValueReason.HookCaptured},
|
||||
{kind: 'Assign', from: '@fn', into: '@returns'},
|
||||
// Note: NO Render effect - callback is not called during render
|
||||
],
|
||||
},
|
||||
},
|
||||
BuiltInUseEffectEventId,
|
||||
);
|
||||
|
||||
// Add as both names for compatibility
|
||||
['useEffectEvent', UseEffectEventHook],
|
||||
['experimental_useEffectEvent', UseEffectEventHook],
|
||||
```
|
||||
|
||||
**Key insight:** If a hook is missing an `aliasing` config, it falls back to `DefaultNonmutatingHook` which includes a `Render` effect on all arguments. This can cause false positives for hooks like `useEffectEvent` whose callbacks are not called during render.
|
||||
|
||||
## Feature Flags
|
||||
|
||||
Feature flags are configured in `src/HIR/Environment.ts`, for example `enableJsxOutlining`. Test fixtures can override the active feature flags used for that fixture via a comment pragma on the first line of the fixture input, for example:
|
||||
|
||||
```javascript
|
||||
// enableJsxOutlining @enableChangeVariableCodegen:false
|
||||
|
||||
...code...
|
||||
```
|
||||
|
||||
Would enable the `enableJsxOutlining` feature and disable the `enableChangeVariableCodegen` feature.
|
||||
|
||||
## Debugging Tips
|
||||
|
||||
1. Run `yarn snap -p <fixture>` to see full HIR output with effects
|
||||
2. Look for `@aliasingEffects=` on FunctionExpressions
|
||||
3. Look for `Impure`, `Render`, `Capture` effects on instructions
|
||||
4. Check the pass ordering in Pipeline.ts to understand when effects are populated vs validated
|
||||
|
||||
## Error Handling for Unsupported Features
|
||||
|
||||
When the compiler encounters an unsupported but known pattern, use `CompilerError.throwTodo()` instead of `CompilerError.invariant()`. Todo errors cause graceful bailouts in production; Invariant errors are hard failures indicating unexpected/invalid states.
|
||||
|
||||
```typescript
|
||||
// Unsupported but expected pattern - graceful bailout
|
||||
CompilerError.throwTodo({
|
||||
reason: `Support [description of unsupported feature]`,
|
||||
loc: terminal.loc,
|
||||
});
|
||||
|
||||
// Invariant is for truly unexpected/invalid states - hard failure
|
||||
CompilerError.invariant(false, {
|
||||
reason: `Unexpected [thing]`,
|
||||
loc: terminal.loc,
|
||||
});
|
||||
```
|
||||
Reference in New Issue
Block a user