3.8 KiB
description
| description |
|---|
| Re-sync src/react_compiler/ against upstream facebook/react. Use when bumping the React Compiler, when upstream lands a fix we need, or when src/react_compiler/UPSTREAM_PORTED is stale. |
Re-syncing the React Compiler
Bun integrates the React Compiler by directly lowering Bun's AST into the
compiler's HIR and directly emitting Bun's AST from codegen, skipping
upstream's Babel-shaped react_compiler_ast intermediate entirely. Nothing is
vendored — every upstream crate Bun uses has been ported into
src/react_compiler/ and is built as part of the bun_react_compiler crate.
There are two kinds of port:
- Whole-crate ports (
hir/,diagnostics/,ssa/,inference/,typeinference/,optimization/,validation/,reactive_scopes/,utils/) — byte-for-byte copies of the upstream crate'ssrc/, modulo crate-name/import rewrites. Upstream diffs apply mechanically. - AST-boundary ports (
lowering/build_hir/,lowering/*.rs,codegen.rs,pipeline.rs,program.rs,imports.rs,compile_result.rs) — re-typed ontobun_astusing the mapping insrc/react_compiler/DESIGN.md. Upstream diffs are re-ported by hand. Upstream'sgating.rsis folded intoprogram.rs;suppression.rsis handled by the lexer (js_parser/lexer.rs) and consumed inprogram.rs;identifier_loc_index.rsis not needed because Bun'sRefalready provides binding identity.
react_compiler_ast, react_compiler_lowering, and the react_compiler
umbrella crate are not in Bun's tree at all — they exist upstream only as
the porting reference for the AST-boundary files.
Sync procedure
-
Produce the upstream diff. The script sparse-fetches facebook/react into a temp dir (nothing is written to the repo) and prints, per ported file, the diff between
src/react_compiler/UPSTREAM_PORTEDand upstream's tip:scripts/sync-react-compiler.sh # or pass an explicit <sha>Output is grouped into three sections: whole-crate ports, AST-boundary ports, and any new upstream file that newly references
react_compiler_ast(i.e. a new boundary file that needs a fresh Bun port). -
Apply whole-crate diffs mechanically. For each hunk under the whole-crate section, apply it to the corresponding
src/react_compiler/<dir>/file. The only systematic edit is import paths (react_compiler_hir::→crate::hir::, etc.); everything else lands verbatim. -
Re-port AST-boundary diffs by hand. For each hunk under the AST-boundary section, re-port it into the named Bun file using the type-mapping table in
src/react_compiler/DESIGN.md: where upstream readsreact_compiler_ast::expressions::Expression::Foo, the Bun port readsbun_ast::expr::Data::EFoo; where upstream constructsreact_compiler_ast::statements::Statement::Foo { … }, the Bun port callsStmt::alloc(S::Foo { … }, loc). Keep control flow, pass ordering, variable names, and comments 1:1 with upstream — only the AST reads/writes change.For large diffs, fan out one agent per file with the upstream diff + the Bun port + DESIGN.md as context, then adversarially review each port.
-
Handle new boundary files. If the third section lists any file, write a fresh Bun port of it under
src/react_compiler/, add it to both arrays inscripts/sync-react-compiler.sh, and add a row to the layout table inDESIGN.md. -
Verify.
cargo check -p bun_react_compiler bun bd test test/bundler/transpiler/react-compiler.test.tsSnapshots will change if codegen changed upstream — review the diff against upstream's new fixture output and update with
bun bd test -uif it matches. -
Update the port marker to the
UPSTREAM_HEADthe script printed:echo <new-sha> > src/react_compiler/UPSTREAM_PORTED