mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-15 06:39:17 +00:00
feat(napi): add React Compiler transform binding (#24934)
Adds the `oxc-transform-react` N-API binding and its public CI and publish workflows. AI-assisted.
This commit is contained in:
27 files changed
+2050
-15
No files matched your search
@@ -61,6 +61,7 @@ pnpm-lock.yaml
|
||||
/crates/oxc_codegen @dunqing
|
||||
/crates/oxc_napi @dunqing
|
||||
/napi/transform @dunqing
|
||||
/napi/transform-react @dunqing
|
||||
/napi/minify @dunqing
|
||||
/npm/runtime @dunqing
|
||||
/tasks/transform_conformance @dunqing
|
||||
|
||||
@@ -37,6 +37,7 @@ A-transformer:
|
||||
"crates/oxc_traverse/**",
|
||||
"tasks/transform_conformance/**",
|
||||
"napi/transform/**",
|
||||
"napi/transform-react/**",
|
||||
]
|
||||
|
||||
A-linter:
|
||||
|
||||
@@ -198,7 +198,7 @@ jobs:
|
||||
id: filter
|
||||
with:
|
||||
exclude: oxc_linter,oxc_language_server
|
||||
paths: napi/parser/,napi/minify/,napi/transform/,npm/oxc-types/,npm/runtime/,tasks/e2e/,pnpm-lock.yaml,package.json
|
||||
paths: napi/parser/,napi/minify/,napi/transform/,napi/transform-react/,npm/oxc-types/,npm/runtime/,tasks/e2e/,pnpm-lock.yaml,package.json
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
pr-number: ${{ github.event.pull_request.number }}
|
||||
- uses: oxc-project/setup-node@4c588e9266bd930b6ddc34307df0659ed511d187 # v1.3.1
|
||||
@@ -222,8 +222,8 @@ jobs:
|
||||
RUN_RAW_RANGE_TESTS: "true"
|
||||
RUN_RAW_TOKENS_TESTS: "true"
|
||||
run: |
|
||||
pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" build-test
|
||||
pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" test
|
||||
pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" --filter "./napi/transform-react" build-test
|
||||
pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" --filter "./napi/transform-react" test
|
||||
- if: steps.filter.outputs.changed == 'true'
|
||||
name: Run e2e tests
|
||||
working-directory: tasks/e2e
|
||||
@@ -343,7 +343,7 @@ jobs:
|
||||
id: filter
|
||||
with:
|
||||
exclude: oxc_linter,oxc_language_server
|
||||
paths: napi/parser/,napi/minify/,napi/transform/,npm/oxc-types/,npm/runtime/,tasks/e2e/,pnpm-lock.yaml,package.json
|
||||
paths: napi/parser/,napi/minify/,napi/transform/,napi/transform-react/,npm/oxc-types/,npm/runtime/,tasks/e2e/,pnpm-lock.yaml,package.json
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
pr-number: ${{ github.event.pull_request.number }}
|
||||
- uses: oxc-project/setup-node@4c588e9266bd930b6ddc34307df0659ed511d187 # v1.3.1
|
||||
@@ -374,8 +374,8 @@ jobs:
|
||||
env:
|
||||
RUN_RAW_RANGE_TESTS: "true"
|
||||
run: |
|
||||
pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" build-test
|
||||
pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" test
|
||||
pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" --filter "./napi/transform-react" build-test
|
||||
pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" --filter "./napi/transform-react" test
|
||||
- if: steps.filter.outputs.changed == 'true'
|
||||
name: Run e2e tests
|
||||
working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}/tasks/e2e
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
name: Release NAPI React Transform
|
||||
|
||||
permissions: {}
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- napi/transform-react/package.json
|
||||
- .github/workflows/release_napi_transform_react.yml
|
||||
- .github/workflows/reusable_release_napi.yml
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: github.repository == 'oxc-project/oxc'
|
||||
name: Release NAPI React Transform
|
||||
uses: ./.github/workflows/reusable_release_napi.yml
|
||||
with:
|
||||
name: transform-react
|
||||
permissions:
|
||||
id-token: write # for `pnpm publish --provenance`
|
||||
Generated
+14
@@ -2718,6 +2718,20 @@ dependencies = [
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxc_transform_react_napi"
|
||||
version = "0.142.0"
|
||||
dependencies = [
|
||||
"mimalloc-safe",
|
||||
"napi",
|
||||
"napi-build",
|
||||
"napi-derive",
|
||||
"oxc",
|
||||
"oxc_napi",
|
||||
"oxc_react_compiler",
|
||||
"oxc_sourcemap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxc_transformer"
|
||||
version = "0.142.0"
|
||||
|
||||
+2
-1
@@ -151,6 +151,7 @@ oxc_span = { version = "0.142.0", path = "crates/oxc_span" } # Source positions
|
||||
oxc_str = { version = "0.142.0", path = "crates/oxc_str" } # String types
|
||||
oxc_syntax = { version = "0.142.0", path = "crates/oxc_syntax" } # Syntax utilities
|
||||
oxc_transform_napi = { version = "0.142.0", path = "napi/transform" } # Node.js transformer binding
|
||||
oxc_transform_react_napi = { version = "0.142.0", path = "napi/transform-react" } # Node.js React Compiler binding
|
||||
oxc_transformer = { version = "0.142.0", path = "crates/oxc_transformer" } # Code transformation
|
||||
oxc_transformer_plugins = { version = "0.142.0", path = "crates/oxc_transformer_plugins" } # Transformer plugins
|
||||
oxc_traverse = { version = "0.142.0", path = "crates/oxc_traverse" } # AST traversal
|
||||
@@ -276,7 +277,7 @@ walkdir = "2.5.0" # Directory traversal
|
||||
windows-sys = { version = "0.61.2" } # Windows API bindings
|
||||
|
||||
[workspace.metadata.cargo-shear]
|
||||
ignored = ["oxc_transform_napi", "oxc_parser_napi", "oxc_minify_napi"]
|
||||
ignored = ["oxc_transform_napi", "oxc_transform_react_napi", "oxc_parser_napi", "oxc_minify_napi"]
|
||||
|
||||
# `oxc_allocator` is both dogfooded here (workspace path) and published to crates.io.
|
||||
# External workspace-dependencies (e.g. `oxc-css-parser`) pull it from the registry,
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this package will be documented in this file.
|
||||
@@ -0,0 +1,54 @@
|
||||
[package]
|
||||
name = "oxc_transform_react_napi"
|
||||
version = "0.142.0"
|
||||
authors.workspace = true
|
||||
categories.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
include = ["/src", "build.rs"]
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
publish = true
|
||||
repository.workspace = true
|
||||
rust-version.workspace = true
|
||||
description.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
oxc = { workspace = true, features = ["full", "react_compiler"] }
|
||||
oxc_napi = { workspace = true }
|
||||
oxc_react_compiler = { workspace = true }
|
||||
oxc_sourcemap = { workspace = true, features = ["napi"] }
|
||||
|
||||
napi = { workspace = true }
|
||||
napi-derive = { workspace = true }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
mimalloc-safe = { workspace = true, optional = true, features = ["skip_collect_on_exit"] }
|
||||
|
||||
[target.'cfg(all(target_os = "linux", not(target_arch = "arm"), not(target_arch = "aarch64")))'.dependencies]
|
||||
mimalloc-safe = { workspace = true, optional = true, features = [
|
||||
"skip_collect_on_exit",
|
||||
"local_dynamic_tls",
|
||||
] }
|
||||
|
||||
[target.'cfg(all(target_os = "linux", target_arch = "aarch64"))'.dependencies]
|
||||
mimalloc-safe = { workspace = true, optional = true, features = [
|
||||
"skip_collect_on_exit",
|
||||
"local_dynamic_tls",
|
||||
"no_opt_arch",
|
||||
] }
|
||||
|
||||
[build-dependencies]
|
||||
napi-build = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
allocator = ["dep:mimalloc-safe"]
|
||||
@@ -0,0 +1,38 @@
|
||||
# Oxc React Transform
|
||||
|
||||
Native Node.js bindings for Oxc's experimental Rust port of React Compiler.
|
||||
|
||||
The API follows `oxc-transform`: pass a filename, source text, and optional
|
||||
options to either `transformSync` or `transform`. React Compiler runs first,
|
||||
then Oxc removes TypeScript syntax and lowers JSX.
|
||||
|
||||
```javascript
|
||||
import { transformSync } from "oxc-transform-react";
|
||||
|
||||
const result = transformSync(
|
||||
"Component.tsx",
|
||||
`
|
||||
export function Component({ name }: { name: string }) {
|
||||
return <div>Hello {name}</div>;
|
||||
}
|
||||
`,
|
||||
{
|
||||
target: "19",
|
||||
},
|
||||
);
|
||||
|
||||
if (result.errors.length > 0) {
|
||||
console.error(result.errors);
|
||||
}
|
||||
|
||||
console.log(result.code);
|
||||
```
|
||||
|
||||
The React Compiler options use the same names as
|
||||
`babel-plugin-react-compiler`/`react-compiler-napi`, including
|
||||
`compilationMode`, `panicThreshold`, `target`, `gating`, `outputMode`,
|
||||
suppression controls, and the supported `environment` flags.
|
||||
|
||||
Callback-valued options such as `logger`, function-valued `sources`, and type
|
||||
provider callbacks are not accepted by the native binding. `sources` accepts
|
||||
an array of filename substrings instead.
|
||||
@@ -0,0 +1 @@
|
||||
export * from '@oxc-transform-react/binding-wasm32-wasi'
|
||||
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
napi_build::setup();
|
||||
}
|
||||
Vendored
+205
@@ -0,0 +1,205 @@
|
||||
/* auto-generated by NAPI-RS */
|
||||
/* eslint-disable */
|
||||
export interface Comment {
|
||||
type: 'Line' | 'Block'
|
||||
value: string
|
||||
start: number
|
||||
end: number
|
||||
}
|
||||
|
||||
export interface ErrorLabel {
|
||||
message: string | null
|
||||
start: number
|
||||
end: number
|
||||
}
|
||||
|
||||
export interface OxcError {
|
||||
severity: Severity
|
||||
message: string
|
||||
labels: Array<ErrorLabel>
|
||||
helpMessage: string | null
|
||||
codeframe: string | null
|
||||
}
|
||||
|
||||
export declare const enum Severity {
|
||||
Error = 'Error',
|
||||
Warning = 'Warning',
|
||||
Advice = 'Advice'
|
||||
}
|
||||
export interface SourceMap {
|
||||
file?: string
|
||||
mappings: string
|
||||
names: Array<string>
|
||||
sourceRoot?: string
|
||||
sources: Array<string>
|
||||
sourcesContent?: Array<string>
|
||||
version: number
|
||||
x_google_ignoreList?: Array<number>
|
||||
}
|
||||
/** Dynamic feature-gating import. */
|
||||
export interface ReactCompilerDynamicGating {
|
||||
source: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial React Compiler environment configuration.
|
||||
*
|
||||
* Unset fields retain compiler defaults. Callback-valued providers and the
|
||||
* compiler's test-only panic switch are intentionally not exposed.
|
||||
*/
|
||||
export interface ReactCompilerEnvironmentOptions {
|
||||
customMacros?: Array<string>
|
||||
enableResetCacheOnSourceFileChanges?: boolean
|
||||
enablePreserveExistingMemoizationGuarantees?: boolean
|
||||
validatePreserveExistingMemoizationGuarantees?: boolean
|
||||
validateExhaustiveMemoizationDependencies?: boolean
|
||||
validateExhaustiveEffectDependencies?: 'off' | 'all' | 'missing-only' | 'extra-only'
|
||||
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 feature-gating import. */
|
||||
export interface ReactCompilerGating {
|
||||
source: string
|
||||
importSpecifierName: string
|
||||
}
|
||||
|
||||
/** Meta-internal React runtime target. */
|
||||
export interface ReactCompilerMetaTarget {
|
||||
kind: 'donotuse_meta_internal'
|
||||
runtimeModule?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a JavaScript or TypeScript React module asynchronously.
|
||||
*
|
||||
* This uses a worker-pool thread and can be slower than `transformSync` for a
|
||||
* single small module.
|
||||
*/
|
||||
export declare function transform(filename: string, sourceText: string, options?: TransformOptions | undefined | null): Promise<TransformResult>
|
||||
|
||||
/**
|
||||
* Options for compiling a JavaScript or TypeScript React module.
|
||||
*
|
||||
* React Compiler fields mirror `babel-plugin-react-compiler` and
|
||||
* `react-compiler-napi`. `lang`, `sourceType`, and `sourcemap` configure the
|
||||
* surrounding Oxc parse/codegen pipeline.
|
||||
*/
|
||||
export interface TransformOptions {
|
||||
/** Treat the source as `js`, `jsx`, `ts`, `tsx`, or `dts`. */
|
||||
lang?: 'js' | 'jsx' | 'ts' | 'tsx' | 'dts'
|
||||
/** Treat the source as script, module, CommonJS, or infer it from syntax. */
|
||||
sourceType?: 'script' | 'module' | 'commonjs' | 'unambiguous'
|
||||
/**
|
||||
* Generate a source map.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
sourcemap?: boolean
|
||||
/**
|
||||
* Which functions the compiler attempts to compile.
|
||||
*
|
||||
* @default 'infer'
|
||||
*/
|
||||
compilationMode?: 'infer' | 'syntax' | 'annotation' | 'all'
|
||||
/**
|
||||
* When compiler diagnostics escalate into a hard failure.
|
||||
*
|
||||
* @default 'none'
|
||||
*/
|
||||
panicThreshold?: 'none' | 'critical_errors' | 'all_errors'
|
||||
/**
|
||||
* React runtime target. React 17 and 18 use `react-compiler-runtime`;
|
||||
* React 19 uses `react/compiler-runtime`.
|
||||
*
|
||||
* @default '19'
|
||||
*/
|
||||
target?: '17' | '18' | '19' | ReactCompilerMetaTarget
|
||||
/** Emit both compiled and original functions behind an imported feature gate. */
|
||||
gating?: ReactCompilerGating
|
||||
/** Enable `"use memo if(...)"` directive-driven gating. */
|
||||
dynamicGating?: ReactCompilerDynamicGating
|
||||
/**
|
||||
* Analyze and report diagnostics without applying compiler output.
|
||||
*
|
||||
* @deprecated Prefer `outputMode: "lint"`.
|
||||
* @default false
|
||||
*/
|
||||
noEmit?: boolean
|
||||
/** Select client, SSR, or lint output. */
|
||||
outputMode?: 'client' | 'ssr' | 'lint'
|
||||
/** ESLint rule names whose suppressions opt a function out of compilation. */
|
||||
eslintSuppressionRules?: Array<string>
|
||||
/**
|
||||
* Treat Flow suppression comments as opt-outs.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
flowSuppressions?: boolean
|
||||
/**
|
||||
* Compile functions carrying `"use no memo"` or `"use no forget"`.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
ignoreUseNoForget?: boolean
|
||||
/** Additional directives that opt a function out of compilation. */
|
||||
customOptOutDirectives?: Array<string>
|
||||
/**
|
||||
* Only run the React Compiler when the filename contains one of these strings.
|
||||
*
|
||||
* Function-valued `sources` filters from the Babel plugin are intentionally
|
||||
* unsupported across the native boundary.
|
||||
*/
|
||||
sources?: Array<string>
|
||||
/** Feature flags and validation settings for compiler passes. */
|
||||
environment?: ReactCompilerEnvironmentOptions
|
||||
}
|
||||
|
||||
/** Result returned by the React Compiler transform. */
|
||||
export interface TransformResult {
|
||||
/**
|
||||
* Transformed JavaScript code.
|
||||
*
|
||||
* This is empty when parsing, semantic analysis, option validation, or the
|
||||
* React Compiler reports a fatal error.
|
||||
*/
|
||||
code: string
|
||||
/** Source map, populated when `sourcemap` is `true`. */
|
||||
map?: SourceMap
|
||||
/** Parse, semantic, React Compiler, and downstream transform diagnostics. */
|
||||
errors: Array<OxcError>
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a JavaScript or TypeScript React module synchronously.
|
||||
*
|
||||
* The React Compiler runs first on the pristine AST. TypeScript and JSX are
|
||||
* lowered afterwards, matching the transform pipeline used by `oxc-transform`.
|
||||
*/
|
||||
export declare function transformSync(filename: string, sourceText: string, options?: TransformOptions | undefined | null): TransformResult
|
||||
@@ -0,0 +1,604 @@
|
||||
// prettier-ignore
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
/* auto-generated by NAPI-RS */
|
||||
|
||||
import { createRequire } from 'module'
|
||||
const require = createRequire(import.meta.url)
|
||||
const __dirname = new URL('.', import.meta.url).pathname
|
||||
|
||||
const { readFileSync } = require('fs')
|
||||
let nativeBinding = null
|
||||
const loadErrors = []
|
||||
|
||||
const isMusl = () => {
|
||||
let musl = false
|
||||
if (process.platform === 'linux') {
|
||||
musl = isMuslFromFilesystem()
|
||||
if (musl === null) {
|
||||
musl = isMuslFromReport()
|
||||
}
|
||||
if (musl === null) {
|
||||
musl = isMuslFromChildProcess()
|
||||
}
|
||||
}
|
||||
return musl
|
||||
}
|
||||
|
||||
const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-')
|
||||
|
||||
const isMuslFromFilesystem = () => {
|
||||
try {
|
||||
return readFileSync('/usr/bin/ldd', 'utf-8').includes('musl')
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const isMuslFromReport = () => {
|
||||
let report = null
|
||||
if (process.report && typeof process.report.getReport === 'function') {
|
||||
process.report.excludeNetwork = true
|
||||
report = process.report.getReport()
|
||||
}
|
||||
if (!report) {
|
||||
return null
|
||||
}
|
||||
if (report.header && report.header.glibcVersionRuntime) {
|
||||
return false
|
||||
}
|
||||
if (Array.isArray(report.sharedObjects)) {
|
||||
if (report.sharedObjects.some(isFileMusl)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const isMuslFromChildProcess = () => {
|
||||
try {
|
||||
return require('child_process').execSync('ldd --version', { encoding: 'utf8' }).includes('musl')
|
||||
} catch (e) {
|
||||
// If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function requireNative() {
|
||||
if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {
|
||||
try {
|
||||
return require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
|
||||
} catch (err) {
|
||||
loadErrors.push(err)
|
||||
}
|
||||
} else if (process.platform === 'android') {
|
||||
if (process.arch === 'arm64') {
|
||||
try {
|
||||
return require('./transform-react.android-arm64.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-android-arm64')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-android-arm64/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else if (process.arch === 'arm') {
|
||||
try {
|
||||
return require('./transform-react.android-arm-eabi.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-android-arm-eabi')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-android-arm-eabi/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
loadErrors.push(new Error(`Unsupported architecture on Android ${process.arch}`))
|
||||
}
|
||||
} else if (process.platform === 'win32') {
|
||||
if (process.arch === 'x64') {
|
||||
if ((process.config && process.config.variables && process.config.variables.shlib_suffix === 'dll.a') || (process.config && process.config.variables && process.config.variables.node_target_type === 'shared_library')) {
|
||||
try {
|
||||
return require('./transform-react.win32-x64-gnu.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-win32-x64-gnu')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-win32-x64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return require('./transform-react.win32-x64-msvc.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-win32-x64-msvc')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-win32-x64-msvc/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
}
|
||||
} else if (process.arch === 'ia32') {
|
||||
try {
|
||||
return require('./transform-react.win32-ia32-msvc.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-win32-ia32-msvc')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-win32-ia32-msvc/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else if (process.arch === 'arm64') {
|
||||
try {
|
||||
return require('./transform-react.win32-arm64-msvc.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-win32-arm64-msvc')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-win32-arm64-msvc/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
loadErrors.push(new Error(`Unsupported architecture on Windows: ${process.arch}`))
|
||||
}
|
||||
} else if (process.platform === 'darwin') {
|
||||
try {
|
||||
return require('./transform-react.darwin-universal.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-darwin-universal')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-darwin-universal/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
if (process.arch === 'x64') {
|
||||
try {
|
||||
return require('./transform-react.darwin-x64.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-darwin-x64')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-darwin-x64/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else if (process.arch === 'arm64') {
|
||||
try {
|
||||
return require('./transform-react.darwin-arm64.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-darwin-arm64')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-darwin-arm64/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
loadErrors.push(new Error(`Unsupported architecture on macOS: ${process.arch}`))
|
||||
}
|
||||
} else if (process.platform === 'freebsd') {
|
||||
if (process.arch === 'x64') {
|
||||
try {
|
||||
return require('./transform-react.freebsd-x64.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-freebsd-x64')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-freebsd-x64/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else if (process.arch === 'arm64') {
|
||||
try {
|
||||
return require('./transform-react.freebsd-arm64.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-freebsd-arm64')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-freebsd-arm64/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
loadErrors.push(new Error(`Unsupported architecture on FreeBSD: ${process.arch}`))
|
||||
}
|
||||
} else if (process.platform === 'linux') {
|
||||
if (process.arch === 'x64') {
|
||||
if (isMusl()) {
|
||||
try {
|
||||
return require('./transform-react.linux-x64-musl.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-x64-musl')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-x64-musl/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return require('./transform-react.linux-x64-gnu.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-x64-gnu')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-x64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
}
|
||||
} else if (process.arch === 'arm64') {
|
||||
if (isMusl()) {
|
||||
try {
|
||||
return require('./transform-react.linux-arm64-musl.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-arm64-musl')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-arm64-musl/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return require('./transform-react.linux-arm64-gnu.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-arm64-gnu')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-arm64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
}
|
||||
} else if (process.arch === 'arm') {
|
||||
if (isMusl()) {
|
||||
try {
|
||||
return require('./transform-react.linux-arm-musleabihf.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-arm-musleabihf')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-arm-musleabihf/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return require('./transform-react.linux-arm-gnueabihf.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-arm-gnueabihf')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-arm-gnueabihf/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
}
|
||||
} else if (process.arch === 'loong64') {
|
||||
if (isMusl()) {
|
||||
try {
|
||||
return require('./transform-react.linux-loong64-musl.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-loong64-musl')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-loong64-musl/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return require('./transform-react.linux-loong64-gnu.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-loong64-gnu')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-loong64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
}
|
||||
} else if (process.arch === 'riscv64') {
|
||||
if (isMusl()) {
|
||||
try {
|
||||
return require('./transform-react.linux-riscv64-musl.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-riscv64-musl')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-riscv64-musl/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return require('./transform-react.linux-riscv64-gnu.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-riscv64-gnu')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-riscv64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
}
|
||||
} else if (process.arch === 'ppc64') {
|
||||
try {
|
||||
return require('./transform-react.linux-ppc64-gnu.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-ppc64-gnu')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-ppc64-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else if (process.arch === 's390x') {
|
||||
try {
|
||||
return require('./transform-react.linux-s390x-gnu.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-linux-s390x-gnu')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-linux-s390x-gnu/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
loadErrors.push(new Error(`Unsupported architecture on Linux: ${process.arch}`))
|
||||
}
|
||||
} else if (process.platform === 'openharmony') {
|
||||
if (process.arch === 'arm64') {
|
||||
try {
|
||||
return require('./transform-react.openharmony-arm64.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-openharmony-arm64')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-openharmony-arm64/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else if (process.arch === 'x64') {
|
||||
try {
|
||||
return require('./transform-react.openharmony-x64.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-openharmony-x64')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-openharmony-x64/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else if (process.arch === 'arm') {
|
||||
try {
|
||||
return require('./transform-react.openharmony-arm.node')
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
try {
|
||||
const binding = require('@oxc-transform-react/binding-openharmony-arm')
|
||||
const bindingPackageVersion = require('@oxc-transform-react/binding-openharmony-arm/package.json').version
|
||||
if (bindingPackageVersion !== '0.142.0' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
|
||||
throw new Error(`Native binding package version mismatch, expected 0.142.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`)
|
||||
}
|
||||
return binding
|
||||
} catch (e) {
|
||||
loadErrors.push(e)
|
||||
}
|
||||
} else {
|
||||
loadErrors.push(new Error(`Unsupported architecture on OpenHarmony: ${process.arch}`))
|
||||
}
|
||||
} else {
|
||||
loadErrors.push(new Error(`Unsupported OS: ${process.platform}, architecture: ${process.arch}`))
|
||||
}
|
||||
}
|
||||
|
||||
nativeBinding = requireNative()
|
||||
|
||||
// NAPI_RS_FORCE_WASI is a tri-state flag:
|
||||
// unset / any other value → native binding preferred, WASI is only a fallback
|
||||
// 'true' → force WASI fallback even if native loaded
|
||||
// 'error' → force WASI and throw if no WASI binding is found
|
||||
// Treating any non-empty string as truthy (the historical behavior) meant
|
||||
// NAPI_RS_FORCE_WASI=false, NAPI_RS_FORCE_WASI=0, etc. inadvertently triggered
|
||||
// the WASI path, causing ENOENT for packages shipped without a .wasi.cjs file.
|
||||
const forceWasi =
|
||||
process.env.NAPI_RS_FORCE_WASI === 'true' || process.env.NAPI_RS_FORCE_WASI === 'error'
|
||||
|
||||
if (!nativeBinding || forceWasi) {
|
||||
let wasiBinding = null
|
||||
let wasiBindingError = null
|
||||
try {
|
||||
wasiBinding = require('./transform-react.wasi.cjs')
|
||||
nativeBinding = wasiBinding
|
||||
} catch (err) {
|
||||
if (forceWasi) {
|
||||
wasiBindingError = err
|
||||
}
|
||||
}
|
||||
if (!nativeBinding || forceWasi) {
|
||||
try {
|
||||
wasiBinding = require('@oxc-transform-react/binding-wasm32-wasi')
|
||||
nativeBinding = wasiBinding
|
||||
} catch (err) {
|
||||
if (forceWasi) {
|
||||
if (!wasiBindingError) {
|
||||
wasiBindingError = err
|
||||
} else {
|
||||
wasiBindingError.cause = err
|
||||
}
|
||||
loadErrors.push(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (process.env.NAPI_RS_FORCE_WASI === 'error' && !wasiBinding) {
|
||||
const error = new Error('WASI binding not found and NAPI_RS_FORCE_WASI is set to error')
|
||||
error.cause = wasiBindingError
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
if (!nativeBinding && globalThis.process?.versions?.["webcontainer"]) {
|
||||
try {
|
||||
nativeBinding = require('./webcontainer-fallback.cjs');
|
||||
} catch (err) {
|
||||
loadErrors.push(err)
|
||||
}
|
||||
}
|
||||
|
||||
if (!nativeBinding) {
|
||||
if (loadErrors.length > 0) {
|
||||
const error = new Error(
|
||||
`Cannot find native binding. ` +
|
||||
`npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). ` +
|
||||
'Please try `npm i` again after removing both package-lock.json and node_modules directory.',
|
||||
)
|
||||
// assign instead of the `new Error(message, { cause })` options form,
|
||||
// which Node < 16.9 silently ignores
|
||||
error.cause = loadErrors.reduce((err, cur) => {
|
||||
cur.cause = err
|
||||
return cur
|
||||
})
|
||||
throw error
|
||||
}
|
||||
throw new Error(`Failed to load native binding`)
|
||||
}
|
||||
|
||||
const { Severity, transform, transformSync } = nativeBinding
|
||||
export { Severity }
|
||||
export { transform }
|
||||
export { transformSync }
|
||||
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"name": "oxc-transform-react",
|
||||
"version": "0.142.0",
|
||||
"description": "Oxc React Compiler Node API",
|
||||
"keywords": [
|
||||
"compiler",
|
||||
"javascript",
|
||||
"jsx",
|
||||
"oxc",
|
||||
"react",
|
||||
"transform",
|
||||
"tsx",
|
||||
"typescript"
|
||||
],
|
||||
"homepage": "https://oxc.rs",
|
||||
"bugs": "https://github.com/oxc-project/oxc/issues",
|
||||
"license": "MIT",
|
||||
"author": "Boshen and oxc contributors",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/oxc-project/oxc.git",
|
||||
"directory": "napi/transform-react"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/Boshen"
|
||||
},
|
||||
"files": [
|
||||
"browser.js",
|
||||
"index.d.ts",
|
||||
"index.js",
|
||||
"webcontainer-fallback.cjs"
|
||||
],
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
"main": "index.js",
|
||||
"browser": "browser.js",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"scripts": {
|
||||
"build-dev": "napi build --esm --platform",
|
||||
"build-test": "pnpm run build-dev --profile coverage",
|
||||
"build": "pnpm run build-dev --features allocator --release",
|
||||
"postbuild": "publint",
|
||||
"postbuild-dev": "node scripts/patch.js",
|
||||
"build-wasm": "pnpm run build-wasm-dev --release",
|
||||
"build-wasm-dev": "pnpm run build-dev --target wasm32-wasip1-threads",
|
||||
"test": "vitest run --dir ./test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@emnapi/core": "catalog:",
|
||||
"@emnapi/runtime": "catalog:",
|
||||
"@napi-rs/cli": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"publint": "catalog:",
|
||||
"vitest": "catalog:"
|
||||
},
|
||||
"napi": {
|
||||
"binaryName": "transform-react",
|
||||
"packageName": "@oxc-transform-react/binding",
|
||||
"targets": [
|
||||
"aarch64-apple-darwin",
|
||||
"aarch64-linux-android",
|
||||
"aarch64-pc-windows-msvc",
|
||||
"aarch64-unknown-linux-gnu",
|
||||
"aarch64-unknown-linux-musl",
|
||||
"aarch64-unknown-linux-ohos",
|
||||
"armv7-linux-androideabi",
|
||||
"armv7-unknown-linux-gnueabihf",
|
||||
"armv7-unknown-linux-musleabihf",
|
||||
"i686-pc-windows-msvc",
|
||||
"powerpc64le-unknown-linux-gnu",
|
||||
"riscv64gc-unknown-linux-gnu",
|
||||
"riscv64gc-unknown-linux-musl",
|
||||
"s390x-unknown-linux-gnu",
|
||||
"wasm32-wasip1-threads",
|
||||
"x86_64-apple-darwin",
|
||||
"x86_64-pc-windows-msvc",
|
||||
"x86_64-unknown-freebsd",
|
||||
"x86_64-unknown-linux-gnu",
|
||||
"x86_64-unknown-linux-musl"
|
||||
],
|
||||
"wasm": {
|
||||
"browser": {
|
||||
"fs": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import fs from "node:fs";
|
||||
import { join as pathJoin } from "node:path";
|
||||
|
||||
const packageDir = pathJoin(import.meta.dirname, "..");
|
||||
const path = pathJoin(packageDir, "index.js");
|
||||
|
||||
let data = fs.readFileSync(path, "utf-8");
|
||||
data = data.replace(
|
||||
"\nif (!nativeBinding) {",
|
||||
(source) =>
|
||||
`
|
||||
if (!nativeBinding && globalThis.process?.versions?.["webcontainer"]) {
|
||||
try {
|
||||
nativeBinding = require('./webcontainer-fallback.cjs');
|
||||
} catch (err) {
|
||||
loadErrors.push(err)
|
||||
}
|
||||
}
|
||||
` + source,
|
||||
);
|
||||
fs.writeFileSync(path, data);
|
||||
|
||||
const workerPath = pathJoin(packageDir, "wasi-worker-browser.mjs");
|
||||
const worker = fs.readFileSync(workerPath, "utf-8").replaceAll(/[ \t]+$/gmu, "");
|
||||
fs.writeFileSync(workerPath, worker);
|
||||
@@ -0,0 +1,167 @@
|
||||
#![expect(clippy::needless_pass_by_value)]
|
||||
|
||||
#[cfg(all(
|
||||
feature = "allocator",
|
||||
not(any(
|
||||
target_arch = "arm",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "windows",
|
||||
target_family = "wasm"
|
||||
))
|
||||
))]
|
||||
#[global_allocator]
|
||||
static ALLOC: mimalloc_safe::MiMalloc = mimalloc_safe::MiMalloc;
|
||||
|
||||
mod options;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use napi::{Task, bindgen_prelude::AsyncTask};
|
||||
use napi_derive::napi;
|
||||
|
||||
use oxc::{
|
||||
CompilerInterface,
|
||||
codegen::CodegenReturn,
|
||||
diagnostics::{Diagnostics, OxcDiagnostic},
|
||||
};
|
||||
use oxc_napi::{OxcError, get_source_type};
|
||||
use oxc_sourcemap::napi::SourceMap;
|
||||
|
||||
pub use crate::options::*;
|
||||
|
||||
/// Result returned by the React Compiler transform.
|
||||
#[derive(Default)]
|
||||
#[napi(object)]
|
||||
pub struct TransformResult {
|
||||
/// Transformed JavaScript code.
|
||||
///
|
||||
/// This is empty when parsing, semantic analysis, option validation, or the
|
||||
/// React Compiler reports a fatal error.
|
||||
pub code: String,
|
||||
|
||||
/// Source map, populated when `sourcemap` is `true`.
|
||||
pub map: Option<SourceMap>,
|
||||
|
||||
/// Parse, semantic, React Compiler, and downstream transform diagnostics.
|
||||
pub errors: Vec<OxcError>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Compiler {
|
||||
transform_options: oxc::transformer::TransformOptions,
|
||||
sourcemap: bool,
|
||||
printed: String,
|
||||
printed_sourcemap: Option<SourceMap>,
|
||||
errors: Diagnostics,
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
fn new(filename: &str, options: Option<TransformOptions>) -> Result<Self, OxcDiagnostic> {
|
||||
let sourcemap = options.as_ref().and_then(|options| options.sourcemap).unwrap_or(false);
|
||||
let transform_options = options.unwrap_or_default().into_transform_options(filename)?;
|
||||
|
||||
Ok(Self {
|
||||
transform_options,
|
||||
sourcemap,
|
||||
printed: String::new(),
|
||||
printed_sourcemap: None,
|
||||
errors: Diagnostics::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl CompilerInterface for Compiler {
|
||||
fn handle_errors(&mut self, errors: Diagnostics) {
|
||||
self.errors.extend(errors);
|
||||
}
|
||||
|
||||
fn enable_sourcemap(&self) -> bool {
|
||||
self.sourcemap
|
||||
}
|
||||
|
||||
fn transform_options(&self) -> Option<&oxc::transformer::TransformOptions> {
|
||||
Some(&self.transform_options)
|
||||
}
|
||||
|
||||
fn after_codegen(&mut self, ret: CodegenReturn<'_>) {
|
||||
self.printed = ret.code;
|
||||
self.printed_sourcemap = ret.map.map(SourceMap::from);
|
||||
}
|
||||
}
|
||||
|
||||
fn transform_impl(
|
||||
filename: &str,
|
||||
source_text: &str,
|
||||
options: Option<TransformOptions>,
|
||||
) -> TransformResult {
|
||||
let source_type = get_source_type(
|
||||
filename,
|
||||
options.as_ref().and_then(|options| options.lang.as_deref()),
|
||||
options.as_ref().and_then(|options| options.source_type.as_deref()),
|
||||
);
|
||||
|
||||
let mut compiler = match Compiler::new(filename, options) {
|
||||
Ok(compiler) => compiler,
|
||||
Err(error) => {
|
||||
return TransformResult {
|
||||
errors: OxcError::from_diagnostics(filename, source_text, [error]),
|
||||
..TransformResult::default()
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
compiler.compile(source_text, source_type, Path::new(filename));
|
||||
|
||||
TransformResult {
|
||||
code: compiler.printed,
|
||||
map: compiler.printed_sourcemap,
|
||||
errors: OxcError::from_diagnostics(filename, source_text, compiler.errors),
|
||||
}
|
||||
}
|
||||
|
||||
/// Compile a JavaScript or TypeScript React module synchronously.
|
||||
///
|
||||
/// The React Compiler runs first on the pristine AST. TypeScript and JSX are
|
||||
/// lowered afterwards, matching the transform pipeline used by `oxc-transform`.
|
||||
#[napi]
|
||||
pub fn transform_sync(
|
||||
filename: String,
|
||||
source_text: String,
|
||||
options: Option<TransformOptions>,
|
||||
) -> TransformResult {
|
||||
transform_impl(&filename, &source_text, options)
|
||||
}
|
||||
|
||||
pub struct TransformTask {
|
||||
filename: String,
|
||||
source_text: String,
|
||||
options: Option<TransformOptions>,
|
||||
}
|
||||
|
||||
#[napi]
|
||||
impl Task for TransformTask {
|
||||
type JsValue = TransformResult;
|
||||
type Output = TransformResult;
|
||||
|
||||
fn compute(&mut self) -> napi::Result<Self::Output> {
|
||||
Ok(transform_impl(&self.filename, &self.source_text, self.options.take()))
|
||||
}
|
||||
|
||||
fn resolve(&mut self, _: napi::Env, result: Self::Output) -> napi::Result<Self::JsValue> {
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
/// Compile a JavaScript or TypeScript React module asynchronously.
|
||||
///
|
||||
/// This uses a worker-pool thread and can be slower than `transformSync` for a
|
||||
/// single small module.
|
||||
#[napi]
|
||||
pub fn transform(
|
||||
filename: String,
|
||||
source_text: String,
|
||||
options: Option<TransformOptions>,
|
||||
) -> AsyncTask<TransformTask> {
|
||||
AsyncTask::new(TransformTask { filename, source_text, options })
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use napi::Either;
|
||||
use napi_derive::napi;
|
||||
|
||||
use oxc::diagnostics::OxcDiagnostic;
|
||||
use oxc_react_compiler::{
|
||||
CompilerTarget, DynamicGatingConfig, EnvironmentConfig, ExhaustiveEffectDepsMode, GatingConfig,
|
||||
PluginOptions,
|
||||
};
|
||||
|
||||
/// Options for compiling a JavaScript or TypeScript React module.
|
||||
///
|
||||
/// React Compiler fields mirror `babel-plugin-react-compiler` and
|
||||
/// `react-compiler-napi`. `lang`, `sourceType`, and `sourcemap` configure the
|
||||
/// surrounding Oxc parse/codegen pipeline.
|
||||
#[napi(object)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct TransformOptions {
|
||||
/// Treat the source as `js`, `jsx`, `ts`, `tsx`, or `dts`.
|
||||
#[napi(ts_type = "'js' | 'jsx' | 'ts' | 'tsx' | 'dts'")]
|
||||
pub lang: Option<String>,
|
||||
|
||||
/// Treat the source as script, module, CommonJS, or infer it from syntax.
|
||||
#[napi(ts_type = "'script' | 'module' | 'commonjs' | 'unambiguous'")]
|
||||
pub source_type: Option<String>,
|
||||
|
||||
/// Generate a source map.
|
||||
///
|
||||
/// @default false
|
||||
pub sourcemap: Option<bool>,
|
||||
|
||||
/// Which functions the compiler attempts to compile.
|
||||
///
|
||||
/// @default 'infer'
|
||||
#[napi(ts_type = "'infer' | 'syntax' | 'annotation' | 'all'")]
|
||||
pub compilation_mode: Option<String>,
|
||||
|
||||
/// When compiler diagnostics escalate into a hard failure.
|
||||
///
|
||||
/// @default 'none'
|
||||
#[napi(ts_type = "'none' | 'critical_errors' | 'all_errors'")]
|
||||
pub panic_threshold: Option<String>,
|
||||
|
||||
/// React runtime target. React 17 and 18 use `react-compiler-runtime`;
|
||||
/// React 19 uses `react/compiler-runtime`.
|
||||
///
|
||||
/// @default '19'
|
||||
#[napi(ts_type = "'17' | '18' | '19' | ReactCompilerMetaTarget")]
|
||||
pub target: Option<Either<String, ReactCompilerMetaTarget>>,
|
||||
|
||||
/// Emit both compiled and original functions behind an imported feature gate.
|
||||
pub gating: Option<ReactCompilerGating>,
|
||||
|
||||
/// Enable `"use memo if(...)"` directive-driven gating.
|
||||
pub dynamic_gating: Option<ReactCompilerDynamicGating>,
|
||||
|
||||
/// Analyze and report diagnostics without applying compiler output.
|
||||
///
|
||||
/// @deprecated Prefer `outputMode: "lint"`.
|
||||
/// @default false
|
||||
pub no_emit: Option<bool>,
|
||||
|
||||
/// Select client, SSR, or lint output.
|
||||
#[napi(ts_type = "'client' | 'ssr' | 'lint'")]
|
||||
pub output_mode: Option<String>,
|
||||
|
||||
/// ESLint rule names whose suppressions opt a function out of compilation.
|
||||
pub eslint_suppression_rules: Option<Vec<String>>,
|
||||
|
||||
/// Treat Flow suppression comments as opt-outs.
|
||||
///
|
||||
/// @default true
|
||||
pub flow_suppressions: Option<bool>,
|
||||
|
||||
/// Compile functions carrying `"use no memo"` or `"use no forget"`.
|
||||
///
|
||||
/// @default false
|
||||
pub ignore_use_no_forget: Option<bool>,
|
||||
|
||||
/// Additional directives that opt a function out of compilation.
|
||||
pub custom_opt_out_directives: Option<Vec<String>>,
|
||||
|
||||
/// Only run the React Compiler when the filename contains one of these strings.
|
||||
///
|
||||
/// Function-valued `sources` filters from the Babel plugin are intentionally
|
||||
/// unsupported across the native boundary.
|
||||
pub sources: Option<Vec<String>>,
|
||||
|
||||
/// Feature flags and validation settings for compiler passes.
|
||||
pub environment: Option<ReactCompilerEnvironmentOptions>,
|
||||
}
|
||||
|
||||
/// Meta-internal React runtime target.
|
||||
#[napi(object)]
|
||||
#[derive(Debug)]
|
||||
pub struct ReactCompilerMetaTarget {
|
||||
#[napi(ts_type = "'donotuse_meta_internal'")]
|
||||
pub kind: String,
|
||||
pub runtime_module: Option<String>,
|
||||
}
|
||||
|
||||
/// Static feature-gating import.
|
||||
#[napi(object)]
|
||||
#[derive(Debug)]
|
||||
pub struct ReactCompilerGating {
|
||||
pub source: String,
|
||||
pub import_specifier_name: String,
|
||||
}
|
||||
|
||||
/// Dynamic feature-gating import.
|
||||
#[napi(object)]
|
||||
#[derive(Debug)]
|
||||
pub struct ReactCompilerDynamicGating {
|
||||
pub source: String,
|
||||
}
|
||||
|
||||
/// Partial React Compiler environment configuration.
|
||||
///
|
||||
/// Unset fields retain compiler defaults. Callback-valued providers and the
|
||||
/// compiler's test-only panic switch are intentionally not exposed.
|
||||
#[napi(object)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ReactCompilerEnvironmentOptions {
|
||||
pub custom_macros: Option<Vec<String>>,
|
||||
pub enable_reset_cache_on_source_file_changes: Option<bool>,
|
||||
pub enable_preserve_existing_memoization_guarantees: Option<bool>,
|
||||
pub validate_preserve_existing_memoization_guarantees: Option<bool>,
|
||||
pub validate_exhaustive_memoization_dependencies: Option<bool>,
|
||||
#[napi(ts_type = "'off' | 'all' | 'missing-only' | 'extra-only'")]
|
||||
pub validate_exhaustive_effect_dependencies: Option<String>,
|
||||
pub enable_optional_dependencies: Option<bool>,
|
||||
pub enable_name_anonymous_functions: Option<bool>,
|
||||
pub validate_hooks_usage: Option<bool>,
|
||||
pub validate_ref_access_during_render: Option<bool>,
|
||||
pub validate_no_set_state_in_render: Option<bool>,
|
||||
pub enable_use_keyed_state: Option<bool>,
|
||||
pub validate_no_set_state_in_effects: Option<bool>,
|
||||
pub validate_no_derived_computations_in_effects: Option<bool>,
|
||||
pub validate_no_derived_computations_in_effects_exp: Option<bool>,
|
||||
pub validate_no_jsx_in_try_statements: Option<bool>,
|
||||
pub validate_static_components: Option<bool>,
|
||||
pub validate_no_capitalized_calls: Option<Vec<String>>,
|
||||
pub validate_blocklisted_imports: Option<Vec<String>>,
|
||||
pub validate_source_locations: Option<bool>,
|
||||
pub validate_no_impure_functions_in_render: Option<bool>,
|
||||
pub validate_no_freezing_known_mutable_functions: Option<bool>,
|
||||
pub enable_assume_hooks_follow_rules_of_react: Option<bool>,
|
||||
pub enable_transitively_freeze_function_expressions: Option<bool>,
|
||||
pub enable_function_outlining: Option<bool>,
|
||||
pub enable_jsx_outlining: Option<bool>,
|
||||
pub assert_valid_mutable_ranges: Option<bool>,
|
||||
pub enable_custom_type_definition_for_reanimated: Option<bool>,
|
||||
pub enable_treat_ref_like_identifiers_as_refs: Option<bool>,
|
||||
pub enable_treat_set_identifiers_as_state_setters: Option<bool>,
|
||||
pub validate_no_void_use_memo: Option<bool>,
|
||||
pub enable_allow_set_state_from_refs_in_effects: Option<bool>,
|
||||
pub enable_verbose_no_set_state_in_effect: Option<bool>,
|
||||
pub enable_forest: Option<bool>,
|
||||
}
|
||||
|
||||
impl TransformOptions {
|
||||
pub(crate) fn into_transform_options(
|
||||
self,
|
||||
filename: &str,
|
||||
) -> Result<oxc::transformer::TransformOptions, OxcDiagnostic> {
|
||||
let enabled = self
|
||||
.sources
|
||||
.as_ref()
|
||||
.is_none_or(|sources| sources.iter().any(|source| filename.contains(source.as_str())));
|
||||
let react_compiler = enabled.then(|| self.into_plugin_options()).transpose()?;
|
||||
|
||||
Ok(oxc::transformer::TransformOptions {
|
||||
react_compiler,
|
||||
jsx: oxc::transformer::JsxOptions::enable(),
|
||||
..oxc::transformer::TransformOptions::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn into_plugin_options(self) -> Result<PluginOptions, OxcDiagnostic> {
|
||||
let mut options = PluginOptions::default();
|
||||
|
||||
if let Some(value) = self.compilation_mode {
|
||||
options.compilation_mode = parse(&value, "compilationMode")?;
|
||||
}
|
||||
if let Some(value) = self.panic_threshold {
|
||||
options.panic_threshold = parse(&value, "panicThreshold")?;
|
||||
}
|
||||
if let Some(target) = self.target {
|
||||
options.target = match target {
|
||||
Either::A(version) => {
|
||||
if !matches!(version.as_str(), "17" | "18" | "19") {
|
||||
return Err(invalid_option("target", &version));
|
||||
}
|
||||
CompilerTarget::Version(version)
|
||||
}
|
||||
Either::B(target) => {
|
||||
if target.kind != "donotuse_meta_internal" {
|
||||
return Err(invalid_option("target.kind", &target.kind));
|
||||
}
|
||||
CompilerTarget::MetaInternal {
|
||||
kind: target.kind,
|
||||
runtime_module: target
|
||||
.runtime_module
|
||||
.unwrap_or_else(|| "react".to_string()),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
if let Some(value) = self.no_emit {
|
||||
options.no_emit = value;
|
||||
}
|
||||
if let Some(value) = self.output_mode {
|
||||
options.output_mode = Some(parse(&value, "outputMode")?);
|
||||
}
|
||||
if let Some(value) = self.flow_suppressions {
|
||||
options.flow_suppressions = value;
|
||||
}
|
||||
if let Some(value) = self.ignore_use_no_forget {
|
||||
options.ignore_use_no_forget = value;
|
||||
}
|
||||
if self.eslint_suppression_rules.is_some() {
|
||||
options.eslint_suppression_rules = self.eslint_suppression_rules;
|
||||
}
|
||||
if self.custom_opt_out_directives.is_some() {
|
||||
options.custom_opt_out_directives = self.custom_opt_out_directives;
|
||||
}
|
||||
if let Some(gating) = self.gating {
|
||||
options.gating = Some(GatingConfig {
|
||||
source: gating.source,
|
||||
import_specifier_name: gating.import_specifier_name,
|
||||
});
|
||||
}
|
||||
if let Some(dynamic_gating) = self.dynamic_gating {
|
||||
options.dynamic_gating = Some(DynamicGatingConfig { source: dynamic_gating.source });
|
||||
}
|
||||
if let Some(environment) = self.environment {
|
||||
environment.apply_to(&mut options.environment)?;
|
||||
}
|
||||
|
||||
Ok(options)
|
||||
}
|
||||
}
|
||||
|
||||
impl ReactCompilerEnvironmentOptions {
|
||||
fn apply_to(self, environment: &mut EnvironmentConfig) -> Result<(), OxcDiagnostic> {
|
||||
macro_rules! apply_bool_options {
|
||||
($($field:ident),+ $(,)?) => {
|
||||
$(
|
||||
if let Some(value) = self.$field {
|
||||
environment.$field = value;
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
if self.custom_macros.is_some() {
|
||||
environment.custom_macros = self.custom_macros;
|
||||
}
|
||||
if self.enable_reset_cache_on_source_file_changes.is_some() {
|
||||
environment.enable_reset_cache_on_source_file_changes =
|
||||
self.enable_reset_cache_on_source_file_changes;
|
||||
}
|
||||
if let Some(value) = self.validate_exhaustive_effect_dependencies {
|
||||
environment.validate_exhaustive_effect_dependencies = match value.as_str() {
|
||||
"off" => ExhaustiveEffectDepsMode::Off,
|
||||
"all" => ExhaustiveEffectDepsMode::All,
|
||||
"missing-only" => ExhaustiveEffectDepsMode::MissingOnly,
|
||||
"extra-only" => ExhaustiveEffectDepsMode::ExtraOnly,
|
||||
_ => {
|
||||
return Err(invalid_option(
|
||||
"environment.validateExhaustiveEffectDependencies",
|
||||
&value,
|
||||
));
|
||||
}
|
||||
};
|
||||
}
|
||||
if self.validate_no_capitalized_calls.is_some() {
|
||||
environment.validate_no_capitalized_calls = self.validate_no_capitalized_calls;
|
||||
}
|
||||
if self.validate_blocklisted_imports.is_some() {
|
||||
environment.validate_blocklisted_imports = self.validate_blocklisted_imports;
|
||||
}
|
||||
|
||||
apply_bool_options!(
|
||||
enable_preserve_existing_memoization_guarantees,
|
||||
validate_preserve_existing_memoization_guarantees,
|
||||
validate_exhaustive_memoization_dependencies,
|
||||
enable_optional_dependencies,
|
||||
enable_name_anonymous_functions,
|
||||
validate_hooks_usage,
|
||||
validate_ref_access_during_render,
|
||||
validate_no_set_state_in_render,
|
||||
enable_use_keyed_state,
|
||||
validate_no_set_state_in_effects,
|
||||
validate_no_derived_computations_in_effects,
|
||||
validate_no_derived_computations_in_effects_exp,
|
||||
validate_no_jsx_in_try_statements,
|
||||
validate_static_components,
|
||||
validate_source_locations,
|
||||
validate_no_impure_functions_in_render,
|
||||
validate_no_freezing_known_mutable_functions,
|
||||
enable_assume_hooks_follow_rules_of_react,
|
||||
enable_transitively_freeze_function_expressions,
|
||||
enable_function_outlining,
|
||||
enable_jsx_outlining,
|
||||
assert_valid_mutable_ranges,
|
||||
enable_custom_type_definition_for_reanimated,
|
||||
enable_treat_ref_like_identifiers_as_refs,
|
||||
enable_treat_set_identifiers_as_state_setters,
|
||||
validate_no_void_use_memo,
|
||||
enable_allow_set_state_from_refs_in_effects,
|
||||
enable_verbose_no_set_state_in_effect,
|
||||
enable_forest,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse<T: FromStr>(value: &str, option: &str) -> Result<T, OxcDiagnostic> {
|
||||
T::from_str(value).map_err(|_| invalid_option(option, value))
|
||||
}
|
||||
|
||||
fn invalid_option(option: &str, value: &str) -> OxcDiagnostic {
|
||||
OxcDiagnostic::error(format!("Invalid React Compiler `{option}` option: `{value}`."))
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { transform, transformSync } from "../index";
|
||||
|
||||
const fixture = `// @license MIT
|
||||
import { useState } from "react";
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export function Component(props: Props) {
|
||||
const [count, setCount] = useState<number>(0);
|
||||
return <button onClick={() => setCount(count + 1)}>{props.text}: {count}</button>;
|
||||
}
|
||||
`;
|
||||
|
||||
describe("transformSync", () => {
|
||||
it("runs React Compiler before TypeScript and JSX transforms", () => {
|
||||
const result = transformSync("Component.tsx", fixture);
|
||||
|
||||
expect(result.errors).toEqual([]);
|
||||
expect(result.code).toContain("react/compiler-runtime");
|
||||
expect(result.code).toContain("_c(");
|
||||
expect(result.code).not.toContain("interface Props");
|
||||
expect(result.code).not.toContain("<button");
|
||||
expect(result.code).toContain("@license MIT");
|
||||
});
|
||||
|
||||
it("forwards React Compiler options", () => {
|
||||
const target = transformSync("Component.tsx", fixture, { target: "18" });
|
||||
expect(target.errors).toEqual([]);
|
||||
expect(target.code).toContain("react-compiler-runtime");
|
||||
|
||||
const gated = transformSync("Component.tsx", fixture, {
|
||||
gating: {
|
||||
source: "feature-flags",
|
||||
importSpecifierName: "isCompilerEnabled",
|
||||
},
|
||||
});
|
||||
expect(gated.errors).toEqual([]);
|
||||
expect(gated.code).toContain("feature-flags");
|
||||
expect(gated.code).toContain("isCompilerEnabled");
|
||||
});
|
||||
|
||||
it("supports dynamic gating and Meta-internal targets", () => {
|
||||
const dynamic = transformSync(
|
||||
"Component.jsx",
|
||||
`export function Component(props) {
|
||||
"use memo if(isCompilerEnabled)";
|
||||
return <div>{props.text}</div>;
|
||||
}`,
|
||||
{
|
||||
dynamicGating: { source: "dynamic-feature-flags" },
|
||||
},
|
||||
);
|
||||
expect(dynamic.errors).toEqual([]);
|
||||
expect(dynamic.code).toContain("dynamic-feature-flags");
|
||||
expect(dynamic.code).toContain("isCompilerEnabled");
|
||||
|
||||
const meta = transformSync("Component.tsx", fixture, {
|
||||
target: {
|
||||
kind: "donotuse_meta_internal",
|
||||
runtimeModule: "custom-react-runtime",
|
||||
},
|
||||
});
|
||||
expect(meta.errors).toEqual([]);
|
||||
expect(meta.code).toContain("custom-react-runtime");
|
||||
});
|
||||
|
||||
it("can override opt-out directives", () => {
|
||||
const source = `function Component(props) {
|
||||
"use no memo";
|
||||
return <div>{props.text}</div>;
|
||||
}`;
|
||||
|
||||
const optedOut = transformSync("Component.jsx", source);
|
||||
expect(optedOut.errors).toEqual([]);
|
||||
expect(optedOut.code).not.toContain("_c(");
|
||||
|
||||
const compiled = transformSync("Component.jsx", source, {
|
||||
ignoreUseNoForget: true,
|
||||
});
|
||||
expect(compiled.errors).toEqual([]);
|
||||
expect(compiled.code).toContain("_c(");
|
||||
});
|
||||
|
||||
it.each([
|
||||
["compilationMode", { compilationMode: "bogus" }],
|
||||
["panicThreshold", { panicThreshold: "bogus" }],
|
||||
["outputMode", { outputMode: "bogus" }],
|
||||
["target", { target: "20" }],
|
||||
[
|
||||
"environment.validateExhaustiveEffectDependencies",
|
||||
{
|
||||
environment: {
|
||||
validateExhaustiveEffectDependencies: "bogus",
|
||||
},
|
||||
},
|
||||
],
|
||||
])("reports an invalid %s option without emitting code", (option, options) => {
|
||||
const result = transformSync("Component.tsx", fixture, options as never);
|
||||
expect(result.code).toBe("");
|
||||
expect(result.errors).toHaveLength(1);
|
||||
expect(result.errors[0].message).toContain(`Invalid React Compiler \`${option}\` option`);
|
||||
});
|
||||
|
||||
it("supports source maps and language overrides", () => {
|
||||
const result = transformSync("Component.vue", fixture, {
|
||||
lang: "tsx",
|
||||
sourcemap: true,
|
||||
});
|
||||
|
||||
expect(result.errors).toEqual([]);
|
||||
expect(result.map).toMatchObject({
|
||||
sources: ["Component.vue"],
|
||||
sourcesContent: [fixture],
|
||||
version: 3,
|
||||
});
|
||||
});
|
||||
|
||||
it("can filter files with sources", () => {
|
||||
const result = transformSync("vendor/Component.tsx", fixture, {
|
||||
sources: ["src/"],
|
||||
});
|
||||
|
||||
expect(result.errors).toEqual([]);
|
||||
expect(result.code).not.toContain("react/compiler-runtime");
|
||||
expect(result.code).not.toContain("interface Props");
|
||||
expect(result.code).not.toContain("<button");
|
||||
});
|
||||
});
|
||||
|
||||
describe("transform", () => {
|
||||
it("matches the synchronous transform", async () => {
|
||||
const sync = transformSync("Component.tsx", fixture);
|
||||
const asyncResult = await transform("Component.tsx", fixture);
|
||||
|
||||
expect(asyncResult).toEqual(sync);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
createOnMessage as __wasmCreateOnMessageForFsProxy,
|
||||
getDefaultContext as __emnapiGetDefaultContext,
|
||||
instantiateNapiModuleSync as __emnapiInstantiateNapiModuleSync,
|
||||
WASI as __WASI,
|
||||
} from '@napi-rs/wasm-runtime'
|
||||
|
||||
|
||||
|
||||
const __wasi = new __WASI({
|
||||
version: 'preview1',
|
||||
})
|
||||
|
||||
const __wasmUrl = new URL('./transform-react.wasm32-wasi.wasm', import.meta.url).href
|
||||
const __emnapiContext = __emnapiGetDefaultContext()
|
||||
|
||||
|
||||
const __sharedMemory = new WebAssembly.Memory({
|
||||
initial: 4000,
|
||||
maximum: 65536,
|
||||
shared: true,
|
||||
})
|
||||
|
||||
const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer())
|
||||
|
||||
const {
|
||||
instance: __napiInstance,
|
||||
module: __wasiModule,
|
||||
napiModule: __napiModule,
|
||||
} = __emnapiInstantiateNapiModuleSync(__wasmFile, {
|
||||
context: __emnapiContext,
|
||||
asyncWorkPoolSize: 4,
|
||||
wasi: __wasi,
|
||||
onCreateWorker() {
|
||||
const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {
|
||||
type: 'module',
|
||||
})
|
||||
|
||||
|
||||
return worker
|
||||
},
|
||||
overwriteImports(importObject) {
|
||||
importObject.env = {
|
||||
...importObject.env,
|
||||
...importObject.napi,
|
||||
...importObject.emnapi,
|
||||
memory: __sharedMemory,
|
||||
}
|
||||
return importObject
|
||||
},
|
||||
beforeInit({ instance }) {
|
||||
for (const name of Object.keys(instance.exports)) {
|
||||
if (name.startsWith('__napi_register__')) {
|
||||
instance.exports[name]()
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
export default __napiModule.exports
|
||||
export const Severity = __napiModule.exports.Severity
|
||||
export const transform = __napiModule.exports.transform
|
||||
export const transformSync = __napiModule.exports.transformSync
|
||||
@@ -0,0 +1,113 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
|
||||
/* auto-generated by NAPI-RS */
|
||||
|
||||
const __nodeFs = require('node:fs')
|
||||
const __nodePath = require('node:path')
|
||||
const { WASI: __nodeWASI } = require('node:wasi')
|
||||
const { Worker } = require('node:worker_threads')
|
||||
|
||||
const {
|
||||
createOnMessage: __wasmCreateOnMessageForFsProxy,
|
||||
getDefaultContext: __emnapiGetDefaultContext,
|
||||
instantiateNapiModuleSync: __emnapiInstantiateNapiModuleSync,
|
||||
} = require('@napi-rs/wasm-runtime')
|
||||
|
||||
const __rootDir = __nodePath.parse(process.cwd()).root
|
||||
|
||||
const __wasi = new __nodeWASI({
|
||||
version: 'preview1',
|
||||
env: process.env,
|
||||
preopens: {
|
||||
[__rootDir]: __rootDir,
|
||||
}
|
||||
})
|
||||
|
||||
const __emnapiContext = __emnapiGetDefaultContext()
|
||||
|
||||
const __sharedMemory = new WebAssembly.Memory({
|
||||
initial: 4000,
|
||||
maximum: 65536,
|
||||
shared: true,
|
||||
})
|
||||
|
||||
let __wasmFilePath = __nodePath.join(__dirname, 'transform-react.wasm32-wasi.wasm')
|
||||
const __wasmDebugFilePath = __nodePath.join(__dirname, 'transform-react.wasm32-wasi.debug.wasm')
|
||||
|
||||
if (__nodeFs.existsSync(__wasmDebugFilePath)) {
|
||||
__wasmFilePath = __wasmDebugFilePath
|
||||
} else if (!__nodeFs.existsSync(__wasmFilePath)) {
|
||||
try {
|
||||
__wasmFilePath = require.resolve('@oxc-transform-react/binding-wasm32-wasi/transform-react.wasm32-wasi.wasm')
|
||||
} catch {
|
||||
throw new Error('Cannot find transform-react.wasm32-wasi.wasm file, and @oxc-transform-react/binding-wasm32-wasi package is not installed.')
|
||||
}
|
||||
}
|
||||
|
||||
const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule } = __emnapiInstantiateNapiModuleSync(__nodeFs.readFileSync(__wasmFilePath), {
|
||||
context: __emnapiContext,
|
||||
asyncWorkPoolSize: (function() {
|
||||
const threadsSizeFromEnv = Number(process.env.NAPI_RS_ASYNC_WORK_POOL_SIZE ?? process.env.UV_THREADPOOL_SIZE)
|
||||
// NaN > 0 is false
|
||||
if (threadsSizeFromEnv > 0) {
|
||||
return threadsSizeFromEnv
|
||||
} else {
|
||||
return 4
|
||||
}
|
||||
})(),
|
||||
reuseWorker: true,
|
||||
wasi: __wasi,
|
||||
onCreateWorker() {
|
||||
const worker = new Worker(__nodePath.join(__dirname, 'wasi-worker.mjs'), {
|
||||
env: process.env,
|
||||
})
|
||||
worker.onmessage = ({ data }) => {
|
||||
__wasmCreateOnMessageForFsProxy(__nodeFs)(data)
|
||||
}
|
||||
|
||||
// The main thread of Node.js waits for all the active handles before exiting.
|
||||
// But Rust threads are never waited without `thread::join`.
|
||||
// So here we hack the code of Node.js to prevent the workers from being referenced (active).
|
||||
// According to https://github.com/nodejs/node/blob/19e0d472728c79d418b74bddff588bea70a403d0/lib/internal/worker.js#L415,
|
||||
// a worker is consist of two handles: kPublicPort and kHandle.
|
||||
{
|
||||
const kPublicPort = Object.getOwnPropertySymbols(worker).find(s =>
|
||||
s.toString().includes("kPublicPort")
|
||||
);
|
||||
if (kPublicPort) {
|
||||
worker[kPublicPort].ref = () => {};
|
||||
}
|
||||
|
||||
const kHandle = Object.getOwnPropertySymbols(worker).find(s =>
|
||||
s.toString().includes("kHandle")
|
||||
);
|
||||
if (kHandle) {
|
||||
worker[kHandle].ref = () => {};
|
||||
}
|
||||
|
||||
worker.unref();
|
||||
}
|
||||
return worker
|
||||
},
|
||||
overwriteImports(importObject) {
|
||||
importObject.env = {
|
||||
...importObject.env,
|
||||
...importObject.napi,
|
||||
...importObject.emnapi,
|
||||
memory: __sharedMemory,
|
||||
}
|
||||
return importObject
|
||||
},
|
||||
beforeInit({ instance }) {
|
||||
for (const name of Object.keys(instance.exports)) {
|
||||
if (name.startsWith('__napi_register__')) {
|
||||
instance.exports[name]()
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
module.exports = __napiModule.exports
|
||||
module.exports.Severity = __napiModule.exports.Severity
|
||||
module.exports.transform = __napiModule.exports.transform
|
||||
module.exports.transformSync = __napiModule.exports.transformSync
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["ESNext"],
|
||||
"module": "Preserve",
|
||||
"moduleResolution": "Bundler",
|
||||
"noEmit": true,
|
||||
"target": "ESNext",
|
||||
"types": ["node"],
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { instantiateNapiModuleSync, MessageHandler, WASI } from '@napi-rs/wasm-runtime'
|
||||
|
||||
const handler = new MessageHandler({
|
||||
onLoad({ wasmModule, wasmMemory }) {
|
||||
const wasi = new WASI({
|
||||
print: function () {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log.apply(console, arguments)
|
||||
},
|
||||
printErr: function() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error.apply(console, arguments)
|
||||
|
||||
},
|
||||
})
|
||||
return instantiateNapiModuleSync(wasmModule, {
|
||||
childThread: true,
|
||||
wasi,
|
||||
overwriteImports(importObject) {
|
||||
importObject.env = {
|
||||
...importObject.env,
|
||||
...importObject.napi,
|
||||
...importObject.emnapi,
|
||||
memory: wasmMemory,
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
globalThis.onmessage = function (e) {
|
||||
handler.handle(e)
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import fs from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import { parse } from "node:path";
|
||||
import { WASI } from "node:wasi";
|
||||
import { parentPort, Worker } from "node:worker_threads";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
const { instantiateNapiModuleSync, MessageHandler, getDefaultContext } = require("@napi-rs/wasm-runtime");
|
||||
|
||||
if (parentPort) {
|
||||
parentPort.on("message", (data) => {
|
||||
globalThis.onmessage({ data });
|
||||
});
|
||||
}
|
||||
|
||||
Object.assign(globalThis, {
|
||||
self: globalThis,
|
||||
require,
|
||||
Worker,
|
||||
importScripts: function (f) {
|
||||
;(0, eval)(fs.readFileSync(f, "utf8") + "//# sourceURL=" + f);
|
||||
},
|
||||
postMessage: function (msg) {
|
||||
if (parentPort) {
|
||||
parentPort.postMessage(msg);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const emnapiContext = getDefaultContext();
|
||||
|
||||
const __rootDir = parse(process.cwd()).root;
|
||||
|
||||
const handler = new MessageHandler({
|
||||
onLoad({ wasmModule, wasmMemory }) {
|
||||
const wasi = new WASI({
|
||||
version: 'preview1',
|
||||
env: process.env,
|
||||
preopens: {
|
||||
[__rootDir]: __rootDir,
|
||||
},
|
||||
});
|
||||
|
||||
return instantiateNapiModuleSync(wasmModule, {
|
||||
childThread: true,
|
||||
wasi,
|
||||
context: emnapiContext,
|
||||
overwriteImports(importObject) {
|
||||
importObject.env = {
|
||||
...importObject.env,
|
||||
...importObject.napi,
|
||||
...importObject.emnapi,
|
||||
memory: wasmMemory
|
||||
};
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
globalThis.onmessage = function (e) {
|
||||
handler.handle(e);
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
const fs = require("node:fs");
|
||||
const childProcess = require("node:child_process");
|
||||
|
||||
const pkg = JSON.parse(
|
||||
fs.readFileSync(require.resolve("oxc-transform-react/package.json"), "utf-8"),
|
||||
);
|
||||
const { version } = pkg;
|
||||
const baseDir = `/tmp/oxc-transform-react-${version}`;
|
||||
const bindingEntry = `${baseDir}/node_modules/@oxc-transform-react/binding-wasm32-wasi/transform-react.wasi.cjs`;
|
||||
|
||||
if (!fs.existsSync(bindingEntry)) {
|
||||
fs.rmSync(baseDir, { recursive: true, force: true });
|
||||
fs.mkdirSync(baseDir, { recursive: true });
|
||||
const bindingPkg = `@oxc-transform-react/binding-wasm32-wasi@${version}`;
|
||||
// oxlint-disable-next-line no-console
|
||||
console.log(`[oxc-transform-react] Downloading ${bindingPkg} on WebContainer...`);
|
||||
childProcess.execFileSync("pnpm", ["i", bindingPkg], {
|
||||
cwd: baseDir,
|
||||
stdio: "inherit",
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = require(bindingEntry);
|
||||
+8
-8
@@ -29,14 +29,14 @@
|
||||
"apps/oxlint/conformance/submodules/**",
|
||||
"napi/parser/src-js/bindings.js",
|
||||
"napi/playground/playground.wasi-browser.js",
|
||||
"napi/{transform,minify,playground}/index.js",
|
||||
"napi/{transform,minify,playground}/index.d.ts",
|
||||
"napi/{parser,transform,minify,playground}/**/index.d.ts",
|
||||
"napi/{parser,transform,minify,playground}/**/*.wasi-browser.js",
|
||||
"napi/{parser,transform,minify,playground}/**/*.wasi.cjs",
|
||||
"napi/{parser,transform,minify,playground}/**/wasi-worker-browser.mjs",
|
||||
"napi/{parser,transform,minify,playground}/**/wasi-worker.mjs",
|
||||
"napi/{parser,transform,minify,playground}/**/browser.js",
|
||||
"napi/{transform,transform-react,minify,playground}/index.js",
|
||||
"napi/{transform,transform-react,minify,playground}/index.d.ts",
|
||||
"napi/{parser,transform,transform-react,minify,playground}/**/index.d.ts",
|
||||
"napi/{parser,transform,transform-react,minify,playground}/**/*.wasi-browser.js",
|
||||
"napi/{parser,transform,transform-react,minify,playground}/**/*.wasi.cjs",
|
||||
"napi/{parser,transform,transform-react,minify,playground}/**/wasi-worker-browser.mjs",
|
||||
"napi/{parser,transform,transform-react,minify,playground}/**/wasi-worker.mjs",
|
||||
"napi/{parser,transform,transform-react,minify,playground}/**/browser.js",
|
||||
"npm/runtime/src",
|
||||
"npm/oxc-types/types.d.ts",
|
||||
"npm/oxfmt/configuration_schema.json",
|
||||
|
||||
Generated
+21
@@ -352,6 +352,27 @@ importers:
|
||||
specifier: 'catalog:'
|
||||
version: 4.1.10(@types/node@24.1.0)(@vitest/browser-playwright@4.1.10)(@vitest/browser-preview@4.1.10)(happy-dom@20.0.11)(vite@7.3.0(@types/node@24.1.0)(lightningcss@1.33.0)(terser@5.44.1)(tsx@4.23.1))
|
||||
|
||||
napi/transform-react:
|
||||
devDependencies:
|
||||
'@emnapi/core':
|
||||
specifier: 'catalog:'
|
||||
version: 1.11.2
|
||||
'@emnapi/runtime':
|
||||
specifier: 'catalog:'
|
||||
version: 1.11.2
|
||||
'@napi-rs/cli':
|
||||
specifier: 'catalog:'
|
||||
version: 3.7.4(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)(@types/node@24.1.0)
|
||||
'@types/node':
|
||||
specifier: 'catalog:'
|
||||
version: 24.1.0
|
||||
publint:
|
||||
specifier: 'catalog:'
|
||||
version: 0.3.22
|
||||
vitest:
|
||||
specifier: 'catalog:'
|
||||
version: 4.1.10(@types/node@24.1.0)(@vitest/browser-playwright@4.1.10)(@vitest/browser-preview@4.1.10)(happy-dom@20.0.11)(vite@7.3.0(@types/node@24.1.0)(lightningcss@1.33.0)(terser@5.44.1)(tsx@4.23.1))
|
||||
|
||||
npm/oxc-types: {}
|
||||
|
||||
npm/oxfmt:
|
||||
|
||||
Reference in new issue
Block a user