Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion crates/oxc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ oxc_isolated_declarations = { workspace = true, optional = true }
oxc_mangler = { workspace = true, optional = true }
oxc_minifier = { workspace = true, optional = true }
oxc_parser = { workspace = true, features = [] }
oxc_react_compiler = { workspace = true, optional = true }
oxc_regular_expression = { workspace = true, optional = true }
oxc_semantic = { workspace = true, optional = true }
oxc_span = { workspace = true }
Expand Down Expand Up @@ -66,7 +67,10 @@ full = [
semantic = ["oxc_semantic"]
transformer = ["oxc_transformer", "oxc_transformer_plugins"]
# Experimental React Compiler pass; off by default (pulls the heavy `oxc_react_compiler` dep).
react_compiler = ["transformer", "oxc_transformer/react_compiler"]
# `dep:oxc_react_compiler` backs the `oxc::react_compiler` re-export, without which
# `TransformOptions::react_compiler` would be a field whose `PluginOptions` type callers
# cannot name.
react_compiler = ["transformer", "oxc_transformer/react_compiler", "dep:oxc_react_compiler"]
minifier = ["oxc_mangler", "oxc_minifier"]
codegen = ["oxc_codegen", "oxc_codegen/sourcemap"]
mangler = ["oxc_mangler"]
Expand Down
13 changes: 13 additions & 0 deletions crates/oxc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,19 @@ pub mod semantic {
pub use oxc_semantic::*;
}

#[cfg(feature = "react_compiler")]
pub mod react_compiler {
//! Experimental React Compiler, run as the first transform pass.
//!
//! Provides the `PluginOptions` that
//! [`crate::transformer::TransformOptions::react_compiler`] takes.
//!
//! See the [`oxc_react_compiler` module-level documentation](oxc_react_compiler) for more
//! information.
#[doc(inline)]
pub use oxc_react_compiler::*;
}

#[cfg(feature = "transformer")]
pub mod transformer {
//! Transformer/Transpiler
Expand Down
10 changes: 9 additions & 1 deletion napi/transform/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,13 @@ mimalloc-safe = { workspace = true, optional = true, features = [
napi-build = { workspace = true }

[features]
default = []
# On by default so the published binary supports the `reactCompiler` option that
# `index.d.ts` advertises. The generated `.d.ts` does not depend on this feature — the
# option types are unconditional (see `src/react_compiler.rs`), so a
# `--no-default-features` build regenerates a byte-identical one and CI's
# `git diff --exit-code` holds either way. Opting out only drops the (heavy) compiler
# from the binary; passing `reactCompiler` to such a build is then a hard error rather
# than a silent no-op.
default = ["react_compiler"]
allocator = ["dep:mimalloc-safe"]
react_compiler = ["oxc/react_compiler"]
147 changes: 144 additions & 3 deletions napi/transform/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,151 @@ export interface ModuleRunnerTransformResult {
export declare function moduleRunnerTransformSync(filename: string, sourceText: string, options?: ModuleRunnerTransformOptions | undefined | null): ModuleRunnerTransformResult

export interface PluginsOptions {
/**
* Enable the experimental [React Compiler](https://github.com/react/react/tree/main/compiler).
*
* `true` enables it with default options; an object enables it with the
* given options; `false` or omitted disables it. When enabled, the compiler
* runs in its own pass before every other transform, memoizing React
* components and hooks.
*
* Requires a build with the `react_compiler` Cargo feature, which is on by
* default; enabling this option against a build without it is an error.
*/
reactCompiler?: boolean | ReactCompilerOptions
styledComponents?: StyledComponentsOptions
taggedTemplateEscape?: boolean
}

/** Dynamic gating for {@link ReactCompilerOptions#dynamicGating}. */
export interface ReactCompilerDynamicGating {
/** Module the gating import comes from. */
source: string
}

/**
* Feature flags and validation toggles for the React Compiler's passes.
*
* Field names mirror the upstream `EnvironmentConfig` one-for-one, so a value that
* works in a Babel `environment` config works here unchanged. Every field is optional;
* omitting one keeps the compiler's default. Several of these gate passes that are off
* by default, so setting them is the only way to reach those diagnostics.
*
* @see {@link ReactCompilerOptions#environment}
*/
export interface ReactCompilerEnvironmentOptions {
customMacros?: Array<string>
enableResetCacheOnSourceFileChanges?: boolean
enablePreserveExistingMemoizationGuarantees?: boolean
validatePreserveExistingMemoizationGuarantees?: boolean
validateExhaustiveMemoizationDependencies?: boolean
enableOptionalDependencies?: boolean
enableNameAnonymousFunctions?: boolean
validateHooksUsage?: boolean
validateRefAccessDuringRender?: boolean
validateNoSetStateInRender?: boolean
enableUseKeyedState?: boolean
validateNoSetStateInEffects?: boolean
validateNoDerivedComputationsInEffects?: boolean
validateNoDerivedComputationsInEffectsExp?: boolean
validateNoJsxInTryStatements?: boolean
validateStaticComponents?: boolean
validateNoCapitalizedCalls?: Array<string>
validateBlocklistedImports?: Array<string>
validateSourceLocations?: boolean
validateNoImpureFunctionsInRender?: boolean
validateNoFreezingKnownMutableFunctions?: boolean
enableAssumeHooksFollowRulesOfReact?: boolean
enableTransitivelyFreezeFunctionExpressions?: boolean
enableFunctionOutlining?: boolean
enableJsxOutlining?: boolean
assertValidMutableRanges?: boolean
enableCustomTypeDefinitionForReanimated?: boolean
enableTreatRefLikeIdentifiersAsRefs?: boolean
enableTreatSetIdentifiersAsStateSetters?: boolean
validateNoVoidUseMemo?: boolean
enableAllowSetStateFromRefsInEffects?: boolean
enableVerboseNoSetStateInEffect?: boolean
enableForest?: boolean
}

/** Static gating for {@link ReactCompilerOptions#gating}. */
export interface ReactCompilerGating {
/** Module the gating import comes from. */
source: string
/** Imported specifier used as the gate. */
importSpecifierName: string
}

/**
* Options for the experimental [React Compiler](https://github.com/react/react/tree/main/compiler).
*
* Mirrors the compiler's `PluginOptions`.
*
* @see {@link PluginsOptions#reactCompiler}
*/
export interface ReactCompilerOptions {
/**
* Which functions to compile.
*
* @default 'infer'
*/
compilationMode?: 'infer' | 'syntax' | 'annotation' | 'all'
/**
* What to do when a function cannot be compiled.
*
* @default 'none'
*/
panicThreshold?: 'none' | 'critical_errors' | 'all_errors'
/**
* React runtime version target. `17` and `18` require the
* `react-compiler-runtime` package; `19` ships the runtime in `react`.
*
* @default '19'
*/
target?: '17' | '18' | '19'
/**
* Analyze and report diagnostics only; emit no transformed code.
*
* @default false
*/
noEmit?: boolean
/**
* Compiler output mode.
*
* @default undefined
*/
outputMode?: 'client' | 'ssr' | 'lint'
/**
* Compile even functions marked with the `"use no memo"` / `"use no forget"`
* opt-out directives.
*
* @default false
*/
ignoreUseNoForget?: boolean
/**
* Treat Flow suppression comments as opt-outs.
*
* @default true
*/
flowSuppressions?: boolean
/** ESLint rules whose suppressions opt a function out of compilation. */
eslintSuppressionRules?: Array<string>
/** Extra directives that opt a function out of compilation. */
customOptOutDirectives?: Array<string>
/** Also emit a gated (feature-flagged) version of each compiled function. */
gating?: ReactCompilerGating
/** Dynamically-gated compilation. */
dynamicGating?: ReactCompilerDynamicGating
/**
* Feature flags and validation toggles for the compilation passes.
*
* Each field left unset keeps the compiler's own default, matching the
* `Partial<EnvironmentConfig>` shape of the upstream Babel plugin's option.
*/
environment?: ReactCompilerEnvironmentOptions
}

export interface ReactRefreshOptions {
/**
* Specify the identifier of the refresh registration variable.
Expand Down Expand Up @@ -448,9 +589,9 @@ export declare function transform(filename: string, sourceText: string, options?
*
* Options are listed in evaluation order: the source is parsed (`lang`,
* `sourceType`), declarations are emitted (`typescript.declaration`), then
* transforms run (`typescript`, `decorator`, `plugins`,
* `jsx`, `target`), followed by the `inject` and `define` plugins, and
* finally codegen (`sourcemap`). `helpers` configures the runtime helpers
* transforms run (`plugins.reactCompiler`, `typescript`, `decorator`,
* `plugins`, `jsx`, `target`), followed by the `inject` and `define` plugins,
* and finally codegen (`sourcemap`). `helpers` configures the runtime helpers
* the transforms emit.
*
* @see {@link transform}
Expand Down
3 changes: 3 additions & 0 deletions napi/transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ static ALLOC: mimalloc_safe::MiMalloc = mimalloc_safe::MiMalloc;
mod isolated_declaration;
pub use isolated_declaration::*;

mod react_compiler;
pub use react_compiler::*;

mod transformer;
pub use transformer::*;
Loading
Loading