compiler/crates/TODO.md MARKDOWN 199 lines View on github.com → Search inside
1# Rust port: e2e parity TODO23Status snapshot (after the current stack lands):45| Variant | Score        | Failures |6| ------- | ------------ | -------- |7| Babel   | 1792 / 1802  | 10       |8| SWC     | 1786 / 1802  | 16       |9| OXC     | 1704 / 1795  | 91       |1011The corpus grew by the three `ts-*` module-interop fixtures (1799 121802 on this branch). The Babel/SWC rows are measured on this branch13and their failure sets are byte-identical to the pre-stack baseline;14the OXC row predates the fixtures and has not been re-measured.1516`cargo test --workspace`: 84 passed, 0 failed.1718## SWC1920(Historical, pre-ts-interop-stack triage on the old staging base; current21snapshot at top.)2223The 15 remaining SWC e2e failures fall into three groups. Each line names the24fixture and the failure mode; the group it sits in dictates the appropriate25fix.2627### Group A: Fixture maintenance, not Rust bugs2829SWC compiles code that TS rejects, or vice versa, in ways where Rust's30behavior is arguably correct. The fix is to rename the fixture (drop the31`error.` prefix) and update the `.expect.md` snapshot so the suite stops32asserting the TS-specific output.3334- `error.bug-invariant-local-or-context-references.js`  TS fires35	`CompilerError::invariant` ("expected all references ... consistently36	local or context"). Rust handles the same code without tripping the37	invariant.38- `error.todo-jsx-intrinsic-tag-matches-local-binding.js`  SWC pipeline39	emits a Todo bailout (`[hoisting] EnterSSA: Expected identifier to be40	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`44	 same as above with the new mutation-aliasing model enabled.45- `error.todo-rust-as-expression-assignment-target.tsx`  Babel errors;46	SWC compiles.47- `fbt/error.todo-locally-require-fbt.js`  Babel emits the48	`Invariant: <fbt> tags should be module-level imports` shape; SWC emits49	`Todo: Local variables named 'fbt' may conflict with the fbt plugin`.50	Different categories, both reasonable.5152### Group B: External dependency5354- `use-no-forget-multiple-with-eslint-suppression.js`  spurious55	`import { c as _c }` in the TS reference output. Fixed on `main` by56	[react#36500](https://github.com/facebook/react/pull/36500) (merged).57	Will pass automatically once `pr-36173` rebases onto `main`; until then58	the TS dist built from `pr-36173` still emits the unused import.5960### Group C: Real SWC frontend bugs6162Each line names the failure mode and a sketch of where to look.6364- `fbt/fbt-param-with-quotes.js`  SWC codegen emits double quotes65	(`"fbt"`) and reformats multi-line JSX into a single line; Babel uses66	single quotes and preserves the source layout. Semantically equivalent67	output; the fix is either an SWC codegen flag for quote style or a68	post-emit pass. Low impact, high effort.6970- `lone-surrogate-string-values.js`  TS preserves lone surrogates71	(`\uD83E`); SWC emits `\uFFFD` because `Wtf8Atom::to_string_lossy()` in72	`react_compiler_swc/src/convert_ast.rs::wtf8_to_string` replaces invalid73	UTF-8 sequences. Real WTF-8 handling work that touches every call site74	using that helper. Probably needs to detect lone surrogates and emit75	`\uXXXX` escapes before they hit `String`.7677- `many-scopes-no-stack-overflow.js`  TS memoizes the function78	(`const $ = _c(401);` with 401 memo slots); SWC pipeline bails out and79	returns the uncompiled source. The fixture exists to test that the80	compiler handles many sequential reactive scopes without stack overflow,81	so the SWC variant should compile. Root cause unclear  needs82	investigation in the SWC pipeline or the compiler core to see where the83	bail happens.8485- `pattern4_bare_type.js`  Two unrelated bugs in one fixture:86	1. Operator-precedence stripping. `Math.round((x - y) * 1000)` becomes87		 `Math.round(x - y * 1000)`. SWC codegen drops the parentheses around88		 the subtraction. Probably in `convert_ast_reverse.rs`'s89		 BinaryExpression handling.90	2. Method return type annotation. `formatMetrics(): Metrics` becomes91		 `formatMetrics()`. The TS-type-on-binding-ident fix in commit92		 cc1ba1e1 only covered binding identifiers; class method signatures93		 are a separate code path. Same shape of fix; different94		 `convert_binding_ident`-equivalent call site.9596- `reduce-reactive-deps/hoist-deps-diff-ssa-instance1.tsx` 97	`(x as HasA).a.value + 2` becomes `(x as HasA.a.value) + 2`. The member98	expression's property chain gets absorbed into the type annotation when99	`convert_ast_reverse` emits the cast. Likely a parenthesization /100	precedence bug in the reverse converter or the SWC printer's handling101	of `TSAsExpression` as the object of a `MemberExpression`.102103- `todo-round2_unicode_string.js` (prefixed `todo-`)  Hex escape format104	(`\xC5`) vs unicode escape (`\u00C5`) for bytes 0x80-0xFF. Both valid JS105	literals; codegen format choice in SWC's string printer.106107- `todo-round3_promote_used_temps.js` (prefixed `todo-`)  Class body108	codegen. TS emits the class with fields and constructor; SWC emits an109	empty class body and pulls fields/methods out into separate assignments.110	Likely an interaction between SWC codegen and the compiler's111	`promote_used_temps` pass.112113- `ts-non-null-expression-default-value.tsx`  Generic type parameter114	support. `const x: ReadonlyMap<string, string> = ...` becomes115	`const x = ...` (annotation dropped entirely). Our116	`convert_ts_type_to_json` helper in cc1ba1e1 explicitly guards against117	`TsTypeRef` with `type_params` to avoid silently emitting118	`ReadonlyMap` without the params. The proper fix needs serialization of119	`TSTypeParameterInstantiation` in `convert_ast.rs` AND deserialization120	in `convert_ast_reverse.rs::convert_ts_type_from_json`.121122## Cross-frontend: TypeScript module interop statements123124Three `ts-*` fixtures pin how TS module-interop statements125(`import x = require(...)`, `export = x`, `export as namespace X`) must126behave: the statement is preserved in output and the file's functions127still compile.128129- **Babel/NAPI** and **SWC** now preserve these end to end. Both flow130	the statements through `Statement::Unknown` (the raw Babel-shaped131	carrier in `react_compiler_ast`); the SWC frontend rebuilds the swc132	module declarations in `convert_ast_reverse.rs` and works around an133	upstream swc_ecma_codegen bug that prints `TsNamespaceExportDecl`134	as `export = X` (`react_compiler_swc/src/ts_namespace_export_fixup.rs`,135	which also carries the guard test that flags when the upstream fix136	lands). Fixtures renamed from `todo-ts-*` to `ts-*`; the137	`SproutTodoFilter` entry for the namespace fixture remains (sprout's138	evaluator cannot evaluate `export as namespace`).139- **OXC** remains deferred: `todo!()` panics in140	`react_compiler_oxc/src/convert_ast.rs` (arms141	`TSImportEqualsDeclaration` / `TSExportAssignment` /142	`TSNamespaceExportDeclaration`; the sibling `TSGlobalDeclaration`143	arm is also unmodeled but unreachable from Babel-parsed fixtures,144	which represent `declare global` as `TSModuleDeclaration`).145146- `ts-import-equals-declaration.ts`147- `ts-export-assignment.ts`148- `ts-namespace-export-declaration.ts`149150## Babel151152(Historical, pre-ts-interop-stack numbers; current snapshot at top.)153154**TODO: scope this out.** Babel is at 1788 / 1795 (7 failures). These have155been the baseline throughout the SWC parity stack and were not touched, so the156failure list is whatever was on `pr-36173` before this work landed.157158Next step is to enumerate the failures by fixture and bucket them the same159way as SWC (fixture maintenance / external dependency / real bugs). Run:160161```bash162bash compiler/scripts/test-e2e.sh --no-color --variant babel163```164165and triage the resulting failures into A/B/C groups under this section.166167## OXC168169(Historical, pre-ts-interop-stack numbers; current snapshot at top.)170171**TODO: scope this out.** OXC is at 1704 / 1795 (91 failures). The CLI172`filename` fix in commit c30f0d6f bumped this by +2 from the 1702 baseline,173but everything else is unaddressed.174175Next step is to enumerate failures and identify OXC-specific clusters176(likely AST conversion gaps in `react_compiler_oxc` analogous to the SWC177work in this stack). Run:178179```bash180bash compiler/scripts/test-e2e.sh --no-color --variant oxc181```182183and bucket the resulting failures into A/B/C groups under this section.184Expect significant overlap with the SWC Group C bugs (cast wrappers,185type annotations, UTF-16/WTF-8 handling) since both frontends share the186post-conversion pipeline.187188## How this stack got here189190(Historical, pre-ts-interop-stack numbers; current snapshot at top.)191192- `compiler/scripts/test-e2e.sh --variant swc` baseline was 1742 / 1795193	(53 failures) before this stack.194- 9 commits in the current stack reduce that to 1780 / 1795 (15 failures,195	-38 fixtures, 72% reduction).196- Babel variant: 1788 / 1795 throughout (no regressions).197- OXC variant: 1702  1704 (the CLI filename commit also benefited OXC).198- `cargo test --workspace`: 56 passed, 0 failed throughout.

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.