Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
Boshen
force-pushed
the
react-compiler-napi
branch
from
July 15, 2026 14:04
253919d to
94c9b83
Compare
Exposes the React Compiler as a Cargo feature on the `oxc` crate and the `oxc-transform` napi binding. `oxc` already had a `react_compiler` feature, but nothing re-exported `oxc_react_compiler`, so enabling it produced a `TransformOptions::react_compiler` field whose `PluginOptions` type callers could not name. Add `oxc::react_compiler`, which also lets the binding build `PluginOptions` through `oxc` instead of depending on the crate directly. Restore the napi `reactCompiler` option, removed in #23590. That change rejected feature-gating because both options it saw were unworkable: unconditional types mean a feature-off build silently ignores the option, and gated types mean `build-test` regenerates a `.d.ts` that no longer matches the checked-in one. Gating below the type surface avoids both -- the JS-facing option types are plain strings and bools, so they stay unconditional and only the conversion into `PluginOptions` is gated. A `--no-default-features` build regenerates a byte-identical `index.d.ts`, and passing `reactCompiler` to such a build is a hard error rather than a silent no-op. The feature is on by default so the published binary supports what the types advertise. It is a default rather than `--features react_compiler` in the build scripts because `build` already passes `--features allocator`, and the napi CLI forwards repeated flags as `--features react_compiler allocator`, which cargo misreads. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Group the option with the other third-party plugin configs as `plugins.reactCompiler`, rather than a top-level `reactCompiler`. The nesting is a JS-API grouping only. `oxc::transformer::PluginsOptions` has no such field -- the transformer runs the compiler as its own pass before the main traversal, off `TransformOptions::react_compiler` -- so `TryFrom<TransformOptions>` lifts the option out of `plugins` before converting the rest. The evaluation-order doc keeps listing it first for that reason. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
`environment` is the option upstream's Babel plugin leads with (`environment: Partial<EnvironmentConfig>`), and it was the one part of `PluginOptions` this binding did not mirror. Without it a JS caller cannot reach the passes that are off by default -- `validateNoSetStateInEffects`, `validateNoDerivedComputationsInEffects`, `enableJsxOutlining` and others -- so the compiler carried roughly 85 KiB of code no caller could execute. Field names mirror `EnvironmentConfig` one-for-one, so an `environment` block that works in a Babel config works here unchanged. Every field is optional; unset fields keep the compiler's default. Not surfaced: the five composite entries (`customHooks`, `moduleTypeProvider`, `enableEmitHookGuards`, `enableEmitInstrumentForget`, `validateExhaustiveEffectDependencies`), and `throwUnknownExceptionTestonly`, which exists to make the compiler panic in upstream's own tests. Upstream defaults were checked against `babel-plugin-react-compiler/src/HIR/Environment.ts`: the flags this port defaults to `false` default to `false` there too. Pragmas remain test-only, matching upstream, where the parser is `parseConfigPragmaForTests` in `Utils/TestUtils.ts`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Boshen
force-pushed
the
react-compiler-napi
branch
from
July 16, 2026 11:48
15c00ae to
62d0731
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Exposes the React Compiler as a Cargo feature on the
oxccrate and theoxc-transformnapi binding, surfaced to JS asplugins.reactCompiler.oxccrate. Thereact_compilerfeature already existed, but nothing re-exportedoxc_react_compiler— so enabling it produced aTransformOptions::react_compiler: Option<PluginOptions>field whose type callers could not name, leaving them to add their own version-matchedoxc_react_compilerdependency. This addsoxc::react_compiler, which is also what lets the binding buildPluginOptionsthroughoxcrather than depending on the crate directly, as it did before #23590.napi binding. Restores the option removed in #23590, now grouped with the other third-party plugin configs as
plugins.reactCompiler. That PR rejected feature-gating because it saw two options, neither workable:build-testregenerates a.d.tsthat no longer matches the checked-in one, breakinggit diff --exit-code.There's a third: gate below the type surface. The JS-facing option types are plain strings and bools with no oxc types, so they stay unconditional and only the conversion into
PluginOptionsis gated. A--no-default-featuresbuild then regenerates a byte-identicalindex.d.ts, sogit diff --exit-codeholds in every feature config, and a lean build passing the option gets a hard error rather than a silent no-op.The feature is on by default so the published binary supports what the types advertise. It's a default rather than
--features react_compilerin the build scripts becausebuildalready passes--features allocator, and the napi CLI forwards repeated flags as--features react_compiler allocator, which cargo misreads.Notes
pluginsis a JS-API grouping only.oxc::transformer::PluginsOptionshas no such field — the transformer runs the compiler as its own pass before the main traversal, offTransformOptions::react_compiler— soTryFrom<TransformOptions>lifts it out ofpluginsbefore converting the rest.TransformOptions's evaluation-order doc still listsplugins.reactCompilerfirst for that reason.default_plugin_options()is gone (nowPluginOptions::default()),compilationMode/panicThreshold/outputModeare enums rather than pass-through strings, andfilename/isDev/enableReanimatedwere dropped in refactor(react_compiler): remove unused js options #24065 as unused no-ops, so those three are no longer surfaced. Unknown enum values are now rejected;targetpreviously fell back to the React 19 runtime silently on a typo and now errors.🤖 Generated with Claude Code