mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(oxc): remove oxc_napi crate (#7634)
napi has a limitation, it cannot feature gate type exposure. closes #7623
This commit is contained in:
parent
e824501a21
commit
771c698a81
22 changed files with 724 additions and 779 deletions
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
|
@ -285,11 +285,12 @@ jobs:
|
|||
- uses: Boshen/setup-rust@main
|
||||
if: steps.filter.outputs.src == 'true'
|
||||
with:
|
||||
save-cache: ${{ github.ref_name == 'main' }}
|
||||
cache-key: warm
|
||||
- uses: ./.github/actions/pnpm
|
||||
if: steps.filter.outputs.src == 'true'
|
||||
- run: pnpm run build
|
||||
- run: pnpm run build-dev
|
||||
if: steps.filter.outputs.src == 'true'
|
||||
- run: pnpm run test
|
||||
if: steps.filter.outputs.src == 'true'
|
||||
- run: git diff --exit-code # Must commit everything
|
||||
if: steps.filter.outputs.src == 'true'
|
||||
|
|
|
|||
45
Cargo.lock
generated
45
Cargo.lock
generated
|
|
@ -403,9 +403,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f"
|
||||
checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
|
|
@ -1067,9 +1067,9 @@ checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
|
|||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
|
||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.6",
|
||||
|
|
@ -1206,9 +1206,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "napi"
|
||||
version = "3.0.0-alpha.14"
|
||||
version = "3.0.0-alpha.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b27505341e98aa6126eb9f56a6ea5d8608959f19f124b9d1f1a694633641e5a"
|
||||
checksum = "04aea9dbe75cd1a1abecf8a66fba1e694c12ce6e6e4e11824dc274e141a6c251"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"ctor",
|
||||
|
|
@ -1225,9 +1225,9 @@ checksum = "e1c0f5d67ee408a4685b61f5ab7e58605c8ae3f2b4189f0127d804ff13d5560a"
|
|||
|
||||
[[package]]
|
||||
name = "napi-derive"
|
||||
version = "3.0.0-alpha.14"
|
||||
version = "3.0.0-alpha.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c98bc3e1aef12e58d9ec48325790838a736f8428ae562716c4df1893b65be22"
|
||||
checksum = "c12428d113f2b64cf827a144dddaf2df50c4d93d655d57d83745c2a281e6ec62"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"napi-derive-backend",
|
||||
|
|
@ -1238,23 +1238,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "napi-derive-backend"
|
||||
version = "2.0.0-alpha.14"
|
||||
version = "2.0.0-alpha.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7fbd5478c5ac30408e4599af0b532726477e347e45fc8b20d95ab1b589057"
|
||||
checksum = "7a5122d26b6f849e524f1b92107364f2b4e9a2e8d41a77b3d6c5b3af75801c60"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"semver",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi-sys"
|
||||
version = "2.4.0"
|
||||
version = "3.0.0-alpha.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "427802e8ec3a734331fec1035594a210ce1ff4dc5bc1950530920ab717964ea3"
|
||||
checksum = "ab9d950ea3a522a8cb9e9237ba7cf977eeca1fadaec182163be6b0feebfc7361"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
|
@ -1377,7 +1376,6 @@ checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56"
|
|||
name = "oxc"
|
||||
version = "0.38.0"
|
||||
dependencies = [
|
||||
"napi",
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
"oxc_cfg",
|
||||
|
|
@ -1787,20 +1785,6 @@ dependencies = [
|
|||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxc_napi"
|
||||
version = "0.38.0"
|
||||
dependencies = [
|
||||
"napi",
|
||||
"napi-derive",
|
||||
"oxc_isolated_declarations",
|
||||
"oxc_sourcemap",
|
||||
"oxc_span",
|
||||
"oxc_syntax",
|
||||
"oxc_transformer",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oxc_parser"
|
||||
version = "0.38.0"
|
||||
|
|
@ -1832,7 +1816,7 @@ dependencies = [
|
|||
"napi-build",
|
||||
"napi-derive",
|
||||
"oxc",
|
||||
"oxc_napi",
|
||||
"rustc-hash",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
|
|
@ -1947,6 +1931,7 @@ dependencies = [
|
|||
"cow-utils",
|
||||
"napi",
|
||||
"napi-derive",
|
||||
"rayon",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
@ -2031,8 +2016,8 @@ dependencies = [
|
|||
"napi-build",
|
||||
"napi-derive",
|
||||
"oxc",
|
||||
"oxc_napi",
|
||||
"oxc_sourcemap",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -91,7 +91,6 @@ oxc_estree = { version = "0.38.0", path = "crates/oxc_estree" }
|
|||
oxc_isolated_declarations = { version = "0.38.0", path = "crates/oxc_isolated_declarations" }
|
||||
oxc_mangler = { version = "0.38.0", path = "crates/oxc_mangler" }
|
||||
oxc_minifier = { version = "0.38.0", path = "crates/oxc_minifier" }
|
||||
oxc_napi = { version = "0.38.0", path = "crates/oxc_napi" }
|
||||
oxc_parser = { version = "0.38.0", path = "crates/oxc_parser" }
|
||||
oxc_regular_expression = { version = "0.38.0", path = "crates/oxc_regular_expression" }
|
||||
oxc_semantic = { version = "0.38.0", path = "crates/oxc_semantic" }
|
||||
|
|
@ -109,9 +108,9 @@ oxc_tasks_common = { path = "tasks/common" }
|
|||
oxc_tasks_transform_checker = { path = "tasks/transform_checker" }
|
||||
|
||||
# Relaxed version so the user can decide which version to use.
|
||||
napi = "3.0.0-alpha"
|
||||
napi = "3.0.0-alpha.11"
|
||||
napi-build = "2.1.3"
|
||||
napi-derive = "3.0.0-alpha"
|
||||
napi-derive = "3.0.0-alpha.11"
|
||||
|
||||
# Relaxed version so the user can decide which version to use.
|
||||
proc-macro2 = "1"
|
||||
|
|
|
|||
|
|
@ -42,8 +42,6 @@ oxc_span = { workspace = true }
|
|||
oxc_syntax = { workspace = true }
|
||||
oxc_transformer = { workspace = true, optional = true }
|
||||
|
||||
napi = { workspace = true, optional = true, features = ["async"] }
|
||||
|
||||
[features]
|
||||
full = [
|
||||
"codegen",
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
[package]
|
||||
name = "oxc_napi"
|
||||
version = "0.38.0"
|
||||
authors.workspace = true
|
||||
categories.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
include = ["/src"]
|
||||
keywords.workspace = true
|
||||
license.workspace = true
|
||||
publish = false
|
||||
repository.workspace = true
|
||||
rust-version.workspace = true
|
||||
description.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[lib]
|
||||
test = false
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
oxc_isolated_declarations = { workspace = true }
|
||||
oxc_sourcemap = { workspace = true, features = ["napi"] }
|
||||
oxc_span = { workspace = true }
|
||||
oxc_syntax = { workspace = true }
|
||||
oxc_transformer = { workspace = true }
|
||||
|
||||
napi = { workspace = true }
|
||||
napi-derive = { workspace = true }
|
||||
|
||||
rustc-hash = { workspace = true }
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
use napi_derive::napi;
|
||||
|
||||
use oxc_sourcemap::napi::SourceMap;
|
||||
|
||||
#[napi(object)]
|
||||
pub struct IsolatedDeclarationsResult {
|
||||
pub code: String,
|
||||
pub map: Option<SourceMap>,
|
||||
pub errors: Vec<String>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub struct IsolatedDeclarationsOptions {
|
||||
/// Do not emit declarations for code that has an @internal annotation in its JSDoc comment.
|
||||
/// This is an internal compiler option; use at your own risk, because the compiler does not check that the result is valid.
|
||||
///
|
||||
/// Default: `false`
|
||||
///
|
||||
/// See <https://www.typescriptlang.org/tsconfig/#stripInternal>
|
||||
pub strip_internal: Option<bool>,
|
||||
|
||||
pub sourcemap: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<IsolatedDeclarationsOptions> for oxc_isolated_declarations::IsolatedDeclarationsOptions {
|
||||
fn from(options: IsolatedDeclarationsOptions) -> Self {
|
||||
Self { strip_internal: options.strip_internal.unwrap_or_default() }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
pub mod parse;
|
||||
|
||||
pub mod isolated_declarations;
|
||||
|
||||
pub mod transform;
|
||||
|
|
@ -1,385 +0,0 @@
|
|||
// NOTE: Types must be aligned with [@types/babel__core](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b5dc32740d9b45d11cff9b025896dd333c795b39/types/babel__core/index.d.ts).
|
||||
|
||||
#![allow(rustdoc::bare_urls)]
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use napi::Either;
|
||||
use napi_derive::napi;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use oxc_sourcemap::napi::SourceMap;
|
||||
use oxc_transformer::{EnvOptions, JsxRuntime, RewriteExtensionsMode};
|
||||
|
||||
use super::isolated_declarations::IsolatedDeclarationsOptions;
|
||||
|
||||
#[derive(Default)]
|
||||
#[napi(object)]
|
||||
pub struct TransformResult {
|
||||
/// The transformed code.
|
||||
///
|
||||
/// If parsing failed, this will be an empty string.
|
||||
pub code: String,
|
||||
|
||||
/// The source map for the transformed code.
|
||||
///
|
||||
/// This will be set if {@link TransformOptions#sourcemap} is `true`.
|
||||
pub map: Option<SourceMap>,
|
||||
|
||||
/// The `.d.ts` declaration file for the transformed code. Declarations are
|
||||
/// only generated if `declaration` is set to `true` and a TypeScript file
|
||||
/// is provided.
|
||||
///
|
||||
/// If parsing failed and `declaration` is set, this will be an empty string.
|
||||
///
|
||||
/// @see {@link TypeScriptOptions#declaration}
|
||||
/// @see [declaration tsconfig option](https://www.typescriptlang.org/tsconfig/#declaration)
|
||||
pub declaration: Option<String>,
|
||||
|
||||
/// Declaration source map. Only generated if both
|
||||
/// {@link TypeScriptOptions#declaration declaration} and
|
||||
/// {@link TransformOptions#sourcemap sourcemap} are set to `true`.
|
||||
pub declaration_map: Option<SourceMap>,
|
||||
|
||||
/// Parse and transformation errors.
|
||||
///
|
||||
/// Oxc's parser recovers from common syntax errors, meaning that
|
||||
/// transformed code may still be available even if there are errors in this
|
||||
/// list.
|
||||
pub errors: Vec<String>,
|
||||
}
|
||||
|
||||
/// Options for transforming a JavaScript or TypeScript file.
|
||||
///
|
||||
/// @see {@link transform}
|
||||
#[napi(object)]
|
||||
#[derive(Default)]
|
||||
pub struct TransformOptions {
|
||||
#[napi(ts_type = "'script' | 'module' | 'unambiguous' | undefined")]
|
||||
pub source_type: Option<String>,
|
||||
|
||||
/// Treat the source text as `js`, `jsx`, `ts`, or `tsx`.
|
||||
#[napi(ts_type = "'js' | 'jsx' | 'ts' | 'tsx'")]
|
||||
pub lang: Option<String>,
|
||||
|
||||
/// The current working directory. Used to resolve relative paths in other
|
||||
/// options.
|
||||
pub cwd: Option<String>,
|
||||
|
||||
/// Enable source map generation.
|
||||
///
|
||||
/// When `true`, the `sourceMap` field of transform result objects will be populated.
|
||||
///
|
||||
/// @default false
|
||||
///
|
||||
/// @see {@link SourceMap}
|
||||
pub sourcemap: Option<bool>,
|
||||
|
||||
/// Set assumptions in order to produce smaller output.
|
||||
pub assumptions: Option<CompilerAssumptions>,
|
||||
|
||||
/// Configure how TypeScript is transformed.
|
||||
pub typescript: Option<TypeScriptOptions>,
|
||||
|
||||
/// Configure how TSX and JSX are transformed.
|
||||
pub jsx: Option<JsxOptions>,
|
||||
|
||||
/// Sets the target environment for the generated JavaScript.
|
||||
///
|
||||
/// The lowest target is `es2015`.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// * 'es2015'
|
||||
/// * ['es2020', 'chrome58', 'edge16', 'firefox57', 'node12', 'safari11']
|
||||
///
|
||||
/// @default `esnext` (No transformation)
|
||||
///
|
||||
/// @see [esbuild#target](https://esbuild.github.io/api/#target)
|
||||
pub target: Option<Either<String, Vec<String>>>,
|
||||
|
||||
/// Define Plugin
|
||||
#[napi(ts_type = "Record<string, string>")]
|
||||
pub define: Option<FxHashMap<String, String>>,
|
||||
|
||||
/// Inject Plugin
|
||||
#[napi(ts_type = "Record<string, string | [string, string]>")]
|
||||
pub inject: Option<FxHashMap<String, Either<String, Vec<String>>>>,
|
||||
}
|
||||
|
||||
impl TryFrom<TransformOptions> for oxc_transformer::TransformOptions {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(options: TransformOptions) -> Result<Self, Self::Error> {
|
||||
let env = match options.target {
|
||||
Some(Either::A(s)) => EnvOptions::from_target(&s)?,
|
||||
Some(Either::B(list)) => EnvOptions::from_target_list(&list)?,
|
||||
_ => EnvOptions::default(),
|
||||
};
|
||||
Ok(Self {
|
||||
cwd: options.cwd.map(PathBuf::from).unwrap_or_default(),
|
||||
assumptions: options.assumptions.map(Into::into).unwrap_or_default(),
|
||||
typescript: options
|
||||
.typescript
|
||||
.map(oxc_transformer::TypeScriptOptions::from)
|
||||
.unwrap_or_default(),
|
||||
jsx: options.jsx.map(Into::into).unwrap_or_default(),
|
||||
env,
|
||||
..Self::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct CompilerAssumptions {
|
||||
pub ignore_function_length: Option<bool>,
|
||||
pub no_document_all: Option<bool>,
|
||||
pub object_rest_no_symbols: Option<bool>,
|
||||
pub pure_getters: Option<bool>,
|
||||
pub set_public_class_fields: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<CompilerAssumptions> for oxc_transformer::CompilerAssumptions {
|
||||
fn from(value: CompilerAssumptions) -> Self {
|
||||
let ops = oxc_transformer::CompilerAssumptions::default();
|
||||
Self {
|
||||
ignore_function_length: value
|
||||
.ignore_function_length
|
||||
.unwrap_or(ops.ignore_function_length),
|
||||
no_document_all: value.no_document_all.unwrap_or(ops.no_document_all),
|
||||
object_rest_no_symbols: value
|
||||
.object_rest_no_symbols
|
||||
.unwrap_or(ops.object_rest_no_symbols),
|
||||
pure_getters: value.pure_getters.unwrap_or(ops.pure_getters),
|
||||
set_public_class_fields: value
|
||||
.set_public_class_fields
|
||||
.unwrap_or(ops.set_public_class_fields),
|
||||
..ops
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
#[derive(Default)]
|
||||
pub struct TypeScriptOptions {
|
||||
pub jsx_pragma: Option<String>,
|
||||
pub jsx_pragma_frag: Option<String>,
|
||||
pub only_remove_type_imports: Option<bool>,
|
||||
pub allow_namespaces: Option<bool>,
|
||||
pub allow_declare_fields: Option<bool>,
|
||||
/// Also generate a `.d.ts` declaration file for TypeScript files.
|
||||
///
|
||||
/// The source file must be compliant with all
|
||||
/// [`isolatedDeclarations`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#isolated-declarations)
|
||||
/// requirements.
|
||||
///
|
||||
/// @default false
|
||||
pub declaration: Option<IsolatedDeclarationsOptions>,
|
||||
/// Rewrite or remove TypeScript import/export declaration extensions.
|
||||
///
|
||||
/// - When set to `rewrite`, it will change `.ts`, `.mts`, `.cts` extensions to `.js`, `.mjs`, `.cjs` respectively.
|
||||
/// - When set to `remove`, it will remove `.ts`/`.mts`/`.cts`/`.tsx` extension entirely.
|
||||
/// - When set to `true`, it's equivalent to `rewrite`.
|
||||
/// - When set to `false` or omitted, no changes will be made to the extensions.
|
||||
///
|
||||
/// @default false
|
||||
#[napi(ts_type = "'rewrite' | 'remove' | boolean")]
|
||||
pub rewrite_import_extensions: Option<Either<bool, String>>,
|
||||
}
|
||||
|
||||
impl From<TypeScriptOptions> for oxc_transformer::TypeScriptOptions {
|
||||
fn from(options: TypeScriptOptions) -> Self {
|
||||
let ops = oxc_transformer::TypeScriptOptions::default();
|
||||
oxc_transformer::TypeScriptOptions {
|
||||
jsx_pragma: options.jsx_pragma.map(Into::into).unwrap_or(ops.jsx_pragma),
|
||||
jsx_pragma_frag: options.jsx_pragma_frag.map(Into::into).unwrap_or(ops.jsx_pragma_frag),
|
||||
only_remove_type_imports: options
|
||||
.only_remove_type_imports
|
||||
.unwrap_or(ops.only_remove_type_imports),
|
||||
allow_namespaces: options.allow_namespaces.unwrap_or(ops.allow_namespaces),
|
||||
allow_declare_fields: options.allow_declare_fields.unwrap_or(ops.allow_declare_fields),
|
||||
optimize_const_enums: false,
|
||||
rewrite_import_extensions: options.rewrite_import_extensions.and_then(|value| {
|
||||
match value {
|
||||
Either::A(v) => {
|
||||
if v {
|
||||
Some(RewriteExtensionsMode::Rewrite)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Either::B(v) => match v.as_str() {
|
||||
"rewrite" => Some(RewriteExtensionsMode::Rewrite),
|
||||
"remove" => Some(RewriteExtensionsMode::Remove),
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure how TSX and JSX are transformed.
|
||||
///
|
||||
/// @see {@link https://babeljs.io/docs/babel-plugin-transform-react-jsx#options}
|
||||
#[napi(object)]
|
||||
pub struct JsxOptions {
|
||||
/// Decides which runtime to use.
|
||||
///
|
||||
/// - 'automatic' - auto-import the correct JSX factories
|
||||
/// - 'classic' - no auto-import
|
||||
///
|
||||
/// @default 'automatic'
|
||||
#[napi(ts_type = "'classic' | 'automatic'")]
|
||||
pub runtime: Option<String>,
|
||||
|
||||
/// Emit development-specific information, such as `__source` and `__self`.
|
||||
///
|
||||
/// @default false
|
||||
///
|
||||
/// @see {@link https://babeljs.io/docs/babel-plugin-transform-react-jsx-development}
|
||||
pub development: Option<bool>,
|
||||
|
||||
/// Toggles whether or not to throw an error if an XML namespaced tag name
|
||||
/// is used.
|
||||
///
|
||||
/// Though the JSX spec allows this, it is disabled by default since React's
|
||||
/// JSX does not currently have support for it.
|
||||
///
|
||||
/// @default true
|
||||
pub throw_if_namespace: Option<bool>,
|
||||
|
||||
/// Enables `@babel/plugin-transform-react-pure-annotations`.
|
||||
///
|
||||
/// It will mark top-level React method calls as pure for tree shaking.
|
||||
///
|
||||
/// @see {@link https://babeljs.io/docs/en/babel-plugin-transform-react-pure-annotations}
|
||||
///
|
||||
/// @default true
|
||||
pub pure: Option<bool>,
|
||||
|
||||
/// Replaces the import source when importing functions.
|
||||
///
|
||||
/// @default 'react'
|
||||
pub import_source: Option<String>,
|
||||
|
||||
/// Replace the function used when compiling JSX expressions. It should be a
|
||||
/// qualified name (e.g. `React.createElement`) or an identifier (e.g.
|
||||
/// `createElement`).
|
||||
///
|
||||
/// Only used for `classic` {@link runtime}.
|
||||
///
|
||||
/// @default 'React.createElement'
|
||||
pub pragma: Option<String>,
|
||||
|
||||
/// Replace the component used when compiling JSX fragments. It should be a
|
||||
/// valid JSX tag name.
|
||||
///
|
||||
/// Only used for `classic` {@link runtime}.
|
||||
///
|
||||
/// @default 'React.Fragment'
|
||||
pub pragma_frag: Option<String>,
|
||||
|
||||
/// When spreading props, use `Object.assign` directly instead of an extend helper.
|
||||
///
|
||||
/// Only used for `classic` {@link runtime}.
|
||||
///
|
||||
/// @default false
|
||||
pub use_built_ins: Option<bool>,
|
||||
|
||||
/// When spreading props, use inline object with spread elements directly
|
||||
/// instead of an extend helper or Object.assign.
|
||||
///
|
||||
/// Only used for `classic` {@link runtime}.
|
||||
///
|
||||
/// @default false
|
||||
pub use_spread: Option<bool>,
|
||||
|
||||
/// Enable React Fast Refresh .
|
||||
///
|
||||
/// Conforms to the implementation in {@link https://github.com/facebook/react/tree/v18.3.1/packages/react-refresh}
|
||||
///
|
||||
/// @default false
|
||||
pub refresh: Option<Either<bool, ReactRefreshOptions>>,
|
||||
}
|
||||
|
||||
impl From<JsxOptions> for oxc_transformer::JsxOptions {
|
||||
fn from(options: JsxOptions) -> Self {
|
||||
let ops = oxc_transformer::JsxOptions::default();
|
||||
oxc_transformer::JsxOptions {
|
||||
runtime: match options.runtime.as_deref() {
|
||||
Some("classic") => JsxRuntime::Classic,
|
||||
/* "automatic" */ _ => JsxRuntime::Automatic,
|
||||
},
|
||||
development: options.development.unwrap_or(ops.development),
|
||||
throw_if_namespace: options.throw_if_namespace.unwrap_or(ops.throw_if_namespace),
|
||||
pure: options.pure.unwrap_or(ops.pure),
|
||||
import_source: options.import_source,
|
||||
pragma: options.pragma,
|
||||
pragma_frag: options.pragma_frag,
|
||||
use_built_ins: options.use_built_ins,
|
||||
use_spread: options.use_spread,
|
||||
refresh: options.refresh.and_then(|value| match value {
|
||||
Either::A(b) => b.then(oxc_transformer::ReactRefreshOptions::default),
|
||||
Either::B(options) => Some(oxc_transformer::ReactRefreshOptions::from(options)),
|
||||
}),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ReactRefreshOptions {
|
||||
/// Specify the identifier of the refresh registration variable.
|
||||
///
|
||||
/// @default `$RefreshReg$`.
|
||||
pub refresh_reg: Option<String>,
|
||||
|
||||
/// Specify the identifier of the refresh signature variable.
|
||||
///
|
||||
/// @default `$RefreshSig$`.
|
||||
pub refresh_sig: Option<String>,
|
||||
|
||||
pub emit_full_signatures: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<ReactRefreshOptions> for oxc_transformer::ReactRefreshOptions {
|
||||
fn from(options: ReactRefreshOptions) -> Self {
|
||||
let ops = oxc_transformer::ReactRefreshOptions::default();
|
||||
oxc_transformer::ReactRefreshOptions {
|
||||
refresh_reg: options.refresh_reg.unwrap_or(ops.refresh_reg),
|
||||
refresh_sig: options.refresh_sig.unwrap_or(ops.refresh_sig),
|
||||
emit_full_signatures: options.emit_full_signatures.unwrap_or(ops.emit_full_signatures),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ArrowFunctionsOptions {
|
||||
/// This option enables the following:
|
||||
/// * Wrap the generated function in .bind(this) and keeps uses of this inside the function as-is, instead of using a renamed this.
|
||||
/// * Add a runtime check to ensure the functions are not instantiated.
|
||||
/// * Add names to arrow functions.
|
||||
///
|
||||
/// @default false
|
||||
pub spec: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<ArrowFunctionsOptions> for oxc_transformer::ArrowFunctionsOptions {
|
||||
fn from(options: ArrowFunctionsOptions) -> Self {
|
||||
oxc_transformer::ArrowFunctionsOptions { spec: options.spec.unwrap_or_default() }
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct Es2015Options {
|
||||
/// Transform arrow functions into function expressions.
|
||||
pub arrow_function: Option<ArrowFunctionsOptions>,
|
||||
}
|
||||
|
||||
impl From<Es2015Options> for oxc_transformer::ES2015Options {
|
||||
fn from(options: Es2015Options) -> Self {
|
||||
oxc_transformer::ES2015Options { arrow_function: options.arrow_function.map(Into::into) }
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
"name": "@oxc-minify/binding",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build-dev": "napi build --platform",
|
||||
"build": "napi build --platform --release",
|
||||
"test": "echo 'skip'"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,12 +21,13 @@ test = false
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
oxc = { workspace = true, features = ["napi", "serialize"] }
|
||||
oxc_napi = { workspace = true }
|
||||
oxc = { workspace = true, features = ["serialize"] }
|
||||
|
||||
rustc-hash = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
napi = { workspace = true, features = ["async"] }
|
||||
napi-derive = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
[package.metadata.cargo-shear]
|
||||
ignored = ["napi"]
|
||||
|
|
|
|||
96
napi/parser/index.d.ts
vendored
96
napi/parser/index.d.ts
vendored
|
|
@ -16,18 +16,6 @@ export interface EcmaScriptModule {
|
|||
staticExports: Array<StaticExport>
|
||||
}
|
||||
|
||||
export interface ExportEntry {
|
||||
start: number
|
||||
end: number
|
||||
moduleRequest?: ValueSpan
|
||||
/** The name under which the desired binding is exported by the module`. */
|
||||
importName: ExportImportName
|
||||
/** The name used to export this binding by this module. */
|
||||
exportName: ExportExportName
|
||||
/** The name that is used to locally access the exported value from within the importing module. */
|
||||
localName: ExportLocalName
|
||||
}
|
||||
|
||||
export interface ExportExportName {
|
||||
kind: ExportExportNameKind
|
||||
name?: string
|
||||
|
|
@ -81,40 +69,6 @@ export declare const enum ExportLocalNameKind {
|
|||
None = 'None'
|
||||
}
|
||||
|
||||
export interface ImportEntry {
|
||||
/**
|
||||
* The name under which the desired binding is exported by the module.
|
||||
*
|
||||
* ```js
|
||||
* import { foo } from "mod";
|
||||
* // ^^^
|
||||
* import { foo as bar } from "mod";
|
||||
* // ^^^
|
||||
* ```
|
||||
*/
|
||||
importName: ImportName
|
||||
/**
|
||||
* The name that is used to locally access the imported value from within the importing module.
|
||||
* ```js
|
||||
* import { foo } from "mod";
|
||||
* // ^^^
|
||||
* import { foo as bar } from "mod";
|
||||
* // ^^^
|
||||
* ```
|
||||
*/
|
||||
localName: ValueSpan
|
||||
/**
|
||||
* Whether this binding is for a TypeScript type-only import.
|
||||
*
|
||||
* `true` for the following imports:
|
||||
* ```ts
|
||||
* import type { foo } from "mod";
|
||||
* import { type foo } from "mod";
|
||||
* ```
|
||||
*/
|
||||
isType: boolean
|
||||
}
|
||||
|
||||
export interface ImportName {
|
||||
kind: ImportNameKind
|
||||
name?: string
|
||||
|
|
@ -174,7 +128,19 @@ export declare function parseWithoutReturn(filename: string, sourceText: string,
|
|||
export interface StaticExport {
|
||||
start: number
|
||||
end: number
|
||||
entries: Array<ExportEntry>
|
||||
entries: Array<StaticExportEntry>
|
||||
}
|
||||
|
||||
export interface StaticExportEntry {
|
||||
start: number
|
||||
end: number
|
||||
moduleRequest?: ValueSpan
|
||||
/** The name under which the desired binding is exported by the module`. */
|
||||
importName: ExportImportName
|
||||
/** The name used to export this binding by this module. */
|
||||
exportName: ExportExportName
|
||||
/** The name that is used to locally access the exported value from within the importing module. */
|
||||
localName: ExportLocalName
|
||||
}
|
||||
|
||||
export interface StaticImport {
|
||||
|
|
@ -196,7 +162,41 @@ export interface StaticImport {
|
|||
*
|
||||
* Empty for `import "mod"`.
|
||||
*/
|
||||
entries: Array<ImportEntry>
|
||||
entries: Array<StaticImportEntry>
|
||||
}
|
||||
|
||||
export interface StaticImportEntry {
|
||||
/**
|
||||
* The name under which the desired binding is exported by the module.
|
||||
*
|
||||
* ```js
|
||||
* import { foo } from "mod";
|
||||
* // ^^^
|
||||
* import { foo as bar } from "mod";
|
||||
* // ^^^
|
||||
* ```
|
||||
*/
|
||||
importName: ImportName
|
||||
/**
|
||||
* The name that is used to locally access the imported value from within the importing module.
|
||||
* ```js
|
||||
* import { foo } from "mod";
|
||||
* // ^^^
|
||||
* import { foo as bar } from "mod";
|
||||
* // ^^^
|
||||
* ```
|
||||
*/
|
||||
localName: ValueSpan
|
||||
/**
|
||||
* Whether this binding is for a TypeScript type-only import.
|
||||
*
|
||||
* `true` for the following imports:
|
||||
* ```ts
|
||||
* import type { foo } from "mod";
|
||||
* import { type foo } from "mod";
|
||||
* ```
|
||||
*/
|
||||
isType: boolean
|
||||
}
|
||||
|
||||
export interface ValueSpan {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
const bindings = require('./bindings.js');
|
||||
|
||||
module.exports.moduleLexerAsync = bindings.moduleLexerAsync;
|
||||
module.exports.moduleLexerSync = bindings.moduleLexerSync;
|
||||
module.exports.parseWithoutReturn = bindings.parseWithoutReturn;
|
||||
|
||||
module.exports.parseAsync = async function parseAsync(...args) {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
"name": "@oxc-parser/binding",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "napi build --platform --release --js bindings.js",
|
||||
"build-dev": "napi build --platform --js bindings.js",
|
||||
"build": "napi build --platform --js bindings.js --release",
|
||||
"test": "vitest --typecheck run ./test"
|
||||
},
|
||||
"napi": {
|
||||
|
|
|
|||
|
|
@ -1,208 +1,15 @@
|
|||
use napi_derive::napi;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use oxc_span::Span;
|
||||
use oxc_syntax::module_record::{self, ModuleRecord};
|
||||
use oxc::{
|
||||
span::Span,
|
||||
syntax::module_record::{self, ModuleRecord},
|
||||
};
|
||||
|
||||
#[napi(object)]
|
||||
#[derive(Default)]
|
||||
pub struct ParserOptions {
|
||||
#[napi(ts_type = "'script' | 'module' | 'unambiguous' | undefined")]
|
||||
pub source_type: Option<String>,
|
||||
|
||||
/// Treat the source text as `js`, `jsx`, `ts`, or `tsx`.
|
||||
#[napi(ts_type = "'js' | 'jsx' | 'ts' | 'tsx'")]
|
||||
pub lang: Option<String>,
|
||||
|
||||
/// Emit `ParenthesizedExpression` in AST.
|
||||
///
|
||||
/// If this option is true, parenthesized expressions are represented by
|
||||
/// (non-standard) `ParenthesizedExpression` nodes that have a single `expression` property
|
||||
/// containing the expression inside parentheses.
|
||||
///
|
||||
/// Default: true
|
||||
pub preserve_parens: Option<bool>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
#[derive(Default)]
|
||||
pub struct ParseResult {
|
||||
#[napi(ts_type = "import(\"@oxc-project/types\").Program")]
|
||||
pub program: String,
|
||||
pub module: EcmaScriptModule,
|
||||
pub comments: Vec<Comment>,
|
||||
pub errors: Vec<String>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct Comment {
|
||||
#[napi(ts_type = "'Line' | 'Block'")]
|
||||
pub r#type: &'static str,
|
||||
pub value: String,
|
||||
pub start: u32,
|
||||
pub end: u32,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
#[derive(Default)]
|
||||
pub struct EcmaScriptModule {
|
||||
/// Import Statements.
|
||||
pub static_imports: Vec<StaticImport>,
|
||||
/// Export Statements.
|
||||
pub static_exports: Vec<StaticExport>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ValueSpan {
|
||||
pub value: String,
|
||||
pub start: u32,
|
||||
pub end: u32,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct StaticImport {
|
||||
/// Start of import statement.
|
||||
pub start: u32,
|
||||
/// End of import statement.
|
||||
pub end: u32,
|
||||
/// Import source.
|
||||
///
|
||||
/// ```js
|
||||
/// import { foo } from "mod";
|
||||
/// // ^^^
|
||||
/// ```
|
||||
pub module_request: ValueSpan,
|
||||
/// Import specifiers.
|
||||
///
|
||||
/// Empty for `import "mod"`.
|
||||
pub entries: Vec<ImportEntry>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ImportEntry {
|
||||
/// The name under which the desired binding is exported by the module.
|
||||
///
|
||||
/// ```js
|
||||
/// import { foo } from "mod";
|
||||
/// // ^^^
|
||||
/// import { foo as bar } from "mod";
|
||||
/// // ^^^
|
||||
/// ```
|
||||
pub import_name: ImportName,
|
||||
/// The name that is used to locally access the imported value from within the importing module.
|
||||
/// ```js
|
||||
/// import { foo } from "mod";
|
||||
/// // ^^^
|
||||
/// import { foo as bar } from "mod";
|
||||
/// // ^^^
|
||||
/// ```
|
||||
pub local_name: ValueSpan,
|
||||
|
||||
/// Whether this binding is for a TypeScript type-only import.
|
||||
///
|
||||
/// `true` for the following imports:
|
||||
/// ```ts
|
||||
/// import type { foo } from "mod";
|
||||
/// import { type foo } from "mod";
|
||||
/// ```
|
||||
pub is_type: bool,
|
||||
}
|
||||
|
||||
#[napi(string_enum)]
|
||||
pub enum ImportNameKind {
|
||||
/// `import { x } from "mod"`
|
||||
Name,
|
||||
/// `import * as ns from "mod"`
|
||||
NamespaceObject,
|
||||
/// `import defaultExport from "mod"`
|
||||
Default,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ImportName {
|
||||
pub kind: ImportNameKind,
|
||||
pub name: Option<String>,
|
||||
pub start: Option<u32>,
|
||||
pub end: Option<u32>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct StaticExport {
|
||||
pub start: u32,
|
||||
pub end: u32,
|
||||
pub entries: Vec<ExportEntry>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ExportEntry {
|
||||
pub start: u32,
|
||||
pub end: u32,
|
||||
pub module_request: Option<ValueSpan>,
|
||||
/// The name under which the desired binding is exported by the module`.
|
||||
pub import_name: ExportImportName,
|
||||
/// The name used to export this binding by this module.
|
||||
pub export_name: ExportExportName,
|
||||
/// The name that is used to locally access the exported value from within the importing module.
|
||||
pub local_name: ExportLocalName,
|
||||
}
|
||||
|
||||
#[napi(string_enum)]
|
||||
pub enum ExportImportNameKind {
|
||||
/// `export { name }
|
||||
Name,
|
||||
/// `export * as ns from "mod"`
|
||||
All,
|
||||
/// `export * from "mod"`
|
||||
AllButDefault,
|
||||
/// Does not have a specifier.
|
||||
None,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ExportImportName {
|
||||
pub kind: ExportImportNameKind,
|
||||
pub name: Option<String>,
|
||||
pub start: Option<u32>,
|
||||
pub end: Option<u32>,
|
||||
}
|
||||
|
||||
#[napi(string_enum)]
|
||||
pub enum ExportExportNameKind {
|
||||
/// `export { name }
|
||||
Name,
|
||||
/// `export default expression`
|
||||
Default,
|
||||
/// `export * from "mod"
|
||||
None,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ExportExportName {
|
||||
pub kind: ExportExportNameKind,
|
||||
pub name: Option<String>,
|
||||
pub start: Option<u32>,
|
||||
pub end: Option<u32>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ExportLocalName {
|
||||
pub kind: ExportLocalNameKind,
|
||||
pub name: Option<String>,
|
||||
pub start: Option<u32>,
|
||||
pub end: Option<u32>,
|
||||
}
|
||||
|
||||
#[napi(string_enum)]
|
||||
pub enum ExportLocalNameKind {
|
||||
/// `export { name }
|
||||
Name,
|
||||
/// `export default expression`
|
||||
Default,
|
||||
/// If the exported value is not locally accessible from within the module.
|
||||
/// `export default function () {}`
|
||||
None,
|
||||
}
|
||||
use crate::types::{
|
||||
EcmaScriptModule, ExportExportName, ExportExportNameKind, ExportImportName,
|
||||
ExportImportNameKind, ExportLocalName, ExportLocalNameKind, ImportName, ImportNameKind,
|
||||
StaticExport, StaticExportEntry, StaticImport, StaticImportEntry, ValueSpan,
|
||||
};
|
||||
|
||||
impl From<&ModuleRecord<'_>> for EcmaScriptModule {
|
||||
fn from(record: &ModuleRecord<'_>) -> Self {
|
||||
|
|
@ -215,7 +22,7 @@ impl From<&ModuleRecord<'_>> for EcmaScriptModule {
|
|||
.import_entries
|
||||
.iter()
|
||||
.filter(|e| e.statement_span == m.statement_span)
|
||||
.map(ImportEntry::from)
|
||||
.map(StaticImportEntry::from)
|
||||
.collect::<Vec<_>>();
|
||||
{
|
||||
StaticImport {
|
||||
|
|
@ -239,10 +46,10 @@ impl From<&ModuleRecord<'_>> for EcmaScriptModule {
|
|||
.iter()
|
||||
.chain(record.indirect_export_entries.iter())
|
||||
.chain(record.star_export_entries.iter())
|
||||
.map(|e| (e.statement_span, ExportEntry::from(e)))
|
||||
.map(|e| (e.statement_span, StaticExportEntry::from(e)))
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.fold(FxHashMap::<Span, Vec<ExportEntry>>::default(), |mut acc, (span, e)| {
|
||||
.fold(FxHashMap::<Span, Vec<StaticExportEntry>>::default(), |mut acc, (span, e)| {
|
||||
acc.entry(span).or_default().push(e);
|
||||
acc
|
||||
})
|
||||
|
|
@ -255,7 +62,20 @@ impl From<&ModuleRecord<'_>> for EcmaScriptModule {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&module_record::ImportEntry<'_>> for ImportEntry {
|
||||
impl From<&module_record::ExportEntry<'_>> for StaticExportEntry {
|
||||
fn from(e: &module_record::ExportEntry) -> Self {
|
||||
Self {
|
||||
start: e.span.start,
|
||||
end: e.span.end,
|
||||
module_request: e.module_request.as_ref().map(ValueSpan::from),
|
||||
import_name: ExportImportName::from(&e.import_name),
|
||||
export_name: ExportExportName::from(&e.export_name),
|
||||
local_name: ExportLocalName::from(&e.local_name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&module_record::ImportEntry<'_>> for StaticImportEntry {
|
||||
fn from(e: &module_record::ImportEntry<'_>) -> Self {
|
||||
Self {
|
||||
import_name: ImportName::from(&e.import_name),
|
||||
|
|
@ -295,19 +115,6 @@ impl From<&module_record::NameSpan<'_>> for ValueSpan {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&module_record::ExportEntry<'_>> for ExportEntry {
|
||||
fn from(e: &module_record::ExportEntry) -> Self {
|
||||
Self {
|
||||
start: e.span.start,
|
||||
end: e.span.end,
|
||||
module_request: e.module_request.as_ref().map(ValueSpan::from),
|
||||
import_name: ExportImportName::from(&e.import_name),
|
||||
export_name: ExportExportName::from(&e.export_name),
|
||||
local_name: ExportLocalName::from(&e.local_name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&module_record::ExportImportName<'_>> for ExportImportName {
|
||||
fn from(e: &module_record::ExportImportName<'_>) -> Self {
|
||||
let (kind, name, start, end) = match e {
|
||||
|
|
@ -2,6 +2,9 @@
|
|||
clippy::needless_pass_by_value // Napi value need to be passed as value
|
||||
)]
|
||||
|
||||
mod convert;
|
||||
mod types;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use napi::{bindgen_prelude::AsyncTask, Task};
|
||||
|
|
@ -14,7 +17,8 @@ use oxc::{
|
|||
parser::{ParseOptions, Parser, ParserReturn},
|
||||
span::SourceType,
|
||||
};
|
||||
use oxc_napi::parse::{Comment, EcmaScriptModule, ParseResult, ParserOptions};
|
||||
|
||||
pub use crate::types::{Comment, EcmaScriptModule, ParseResult, ParserOptions};
|
||||
|
||||
fn get_source_type(filename: &str, options: &ParserOptions) -> SourceType {
|
||||
match options.lang.as_deref() {
|
||||
|
|
@ -83,8 +87,8 @@ fn parse_with_return(filename: &str, source_text: &str, options: &ParserOptions)
|
|||
.iter()
|
||||
.map(|comment| Comment {
|
||||
r#type: match comment.kind {
|
||||
CommentKind::Line => "Line",
|
||||
CommentKind::Block => "Block",
|
||||
CommentKind::Line => String::from("Line"),
|
||||
CommentKind::Block => String::from("Block"),
|
||||
},
|
||||
value: comment.content_span().source_text(source_text).to_string(),
|
||||
start: comment.span.start,
|
||||
|
|
|
|||
198
napi/parser/src/types.rs
Normal file
198
napi/parser/src/types.rs
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
use napi_derive::napi;
|
||||
|
||||
#[napi(object)]
|
||||
#[derive(Default)]
|
||||
pub struct ParserOptions {
|
||||
#[napi(ts_type = "'script' | 'module' | 'unambiguous' | undefined")]
|
||||
pub source_type: Option<String>,
|
||||
|
||||
/// Treat the source text as `js`, `jsx`, `ts`, or `tsx`.
|
||||
#[napi(ts_type = "'js' | 'jsx' | 'ts' | 'tsx'")]
|
||||
pub lang: Option<String>,
|
||||
|
||||
/// Emit `ParenthesizedExpression` in AST.
|
||||
///
|
||||
/// If this option is true, parenthesized expressions are represented by
|
||||
/// (non-standard) `ParenthesizedExpression` nodes that have a single `expression` property
|
||||
/// containing the expression inside parentheses.
|
||||
///
|
||||
/// Default: true
|
||||
pub preserve_parens: Option<bool>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ParseResult {
|
||||
#[napi(ts_type = "import(\"@oxc-project/types\").Program")]
|
||||
pub program: String,
|
||||
pub module: EcmaScriptModule,
|
||||
pub comments: Vec<Comment>,
|
||||
pub errors: Vec<String>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct Comment {
|
||||
#[napi(ts_type = "'Line' | 'Block'")]
|
||||
pub r#type: String,
|
||||
pub value: String,
|
||||
pub start: u32,
|
||||
pub end: u32,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct EcmaScriptModule {
|
||||
/// Import Statements.
|
||||
pub static_imports: Vec<StaticImport>,
|
||||
/// Export Statements.
|
||||
pub static_exports: Vec<StaticExport>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ValueSpan {
|
||||
pub value: String,
|
||||
pub start: u32,
|
||||
pub end: u32,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct StaticImport {
|
||||
/// Start of import statement.
|
||||
pub start: u32,
|
||||
/// End of import statement.
|
||||
pub end: u32,
|
||||
/// Import source.
|
||||
///
|
||||
/// ```js
|
||||
/// import { foo } from "mod";
|
||||
/// // ^^^
|
||||
/// ```
|
||||
pub module_request: ValueSpan,
|
||||
/// Import specifiers.
|
||||
///
|
||||
/// Empty for `import "mod"`.
|
||||
pub entries: Vec<StaticImportEntry>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct StaticImportEntry {
|
||||
/// The name under which the desired binding is exported by the module.
|
||||
///
|
||||
/// ```js
|
||||
/// import { foo } from "mod";
|
||||
/// // ^^^
|
||||
/// import { foo as bar } from "mod";
|
||||
/// // ^^^
|
||||
/// ```
|
||||
pub import_name: ImportName,
|
||||
/// The name that is used to locally access the imported value from within the importing module.
|
||||
/// ```js
|
||||
/// import { foo } from "mod";
|
||||
/// // ^^^
|
||||
/// import { foo as bar } from "mod";
|
||||
/// // ^^^
|
||||
/// ```
|
||||
pub local_name: ValueSpan,
|
||||
|
||||
/// Whether this binding is for a TypeScript type-only import.
|
||||
///
|
||||
/// `true` for the following imports:
|
||||
/// ```ts
|
||||
/// import type { foo } from "mod";
|
||||
/// import { type foo } from "mod";
|
||||
/// ```
|
||||
pub is_type: bool,
|
||||
}
|
||||
|
||||
#[napi(string_enum)]
|
||||
pub enum ImportNameKind {
|
||||
/// `import { x } from "mod"`
|
||||
Name,
|
||||
/// `import * as ns from "mod"`
|
||||
NamespaceObject,
|
||||
/// `import defaultExport from "mod"`
|
||||
Default,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ImportName {
|
||||
pub kind: ImportNameKind,
|
||||
pub name: Option<String>,
|
||||
pub start: Option<u32>,
|
||||
pub end: Option<u32>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct StaticExportEntry {
|
||||
pub start: u32,
|
||||
pub end: u32,
|
||||
pub module_request: Option<ValueSpan>,
|
||||
/// The name under which the desired binding is exported by the module`.
|
||||
pub import_name: ExportImportName,
|
||||
/// The name used to export this binding by this module.
|
||||
pub export_name: ExportExportName,
|
||||
/// The name that is used to locally access the exported value from within the importing module.
|
||||
pub local_name: ExportLocalName,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct StaticExport {
|
||||
pub start: u32,
|
||||
pub end: u32,
|
||||
pub entries: Vec<StaticExportEntry>,
|
||||
}
|
||||
|
||||
#[napi(string_enum)]
|
||||
pub enum ExportImportNameKind {
|
||||
/// `export { name }
|
||||
Name,
|
||||
/// `export * as ns from "mod"`
|
||||
All,
|
||||
/// `export * from "mod"`
|
||||
AllButDefault,
|
||||
/// Does not have a specifier.
|
||||
None,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ExportImportName {
|
||||
pub kind: ExportImportNameKind,
|
||||
pub name: Option<String>,
|
||||
pub start: Option<u32>,
|
||||
pub end: Option<u32>,
|
||||
}
|
||||
|
||||
#[napi(string_enum)]
|
||||
pub enum ExportExportNameKind {
|
||||
/// `export { name }
|
||||
Name,
|
||||
/// `export default expression`
|
||||
Default,
|
||||
/// `export * from "mod"
|
||||
None,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ExportExportName {
|
||||
pub kind: ExportExportNameKind,
|
||||
pub name: Option<String>,
|
||||
pub start: Option<u32>,
|
||||
pub end: Option<u32>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ExportLocalName {
|
||||
pub kind: ExportLocalNameKind,
|
||||
pub name: Option<String>,
|
||||
pub start: Option<u32>,
|
||||
pub end: Option<u32>,
|
||||
}
|
||||
|
||||
#[napi(string_enum)]
|
||||
pub enum ExportLocalNameKind {
|
||||
/// `export { name }
|
||||
Name,
|
||||
/// `export default expression`
|
||||
Default,
|
||||
/// If the exported value is not locally accessible from within the module.
|
||||
/// `export default function () {}`
|
||||
None,
|
||||
}
|
||||
|
|
@ -21,9 +21,10 @@ test = false
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
oxc = { workspace = true, features = ["full", "napi"] }
|
||||
oxc_napi = { workspace = true }
|
||||
oxc_sourcemap = { workspace = true, features = ["napi"] }
|
||||
oxc = { workspace = true, features = ["full"] }
|
||||
oxc_sourcemap = { workspace = true, features = ["napi", "rayon"] }
|
||||
|
||||
rustc-hash = { workspace = true }
|
||||
|
||||
napi = { workspace = true }
|
||||
napi-derive = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
"name": "@oxc-transform/binding",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build-dev": "napi build --platform",
|
||||
"build": "napi build --platform --release",
|
||||
"test": "vitest --typecheck run ./test"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,11 +9,38 @@ use oxc::{
|
|||
parser::Parser,
|
||||
span::SourceType,
|
||||
};
|
||||
use oxc_napi::isolated_declarations::{IsolatedDeclarationsOptions, IsolatedDeclarationsResult};
|
||||
use oxc_sourcemap::napi::SourceMap;
|
||||
|
||||
use crate::errors::wrap_diagnostics;
|
||||
|
||||
use oxc_sourcemap::napi::SourceMap;
|
||||
|
||||
#[napi(object)]
|
||||
pub struct IsolatedDeclarationsResult {
|
||||
pub code: String,
|
||||
pub map: Option<SourceMap>,
|
||||
pub errors: Vec<String>,
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub struct IsolatedDeclarationsOptions {
|
||||
/// Do not emit declarations for code that has an @internal annotation in its JSDoc comment.
|
||||
/// This is an internal compiler option; use at your own risk, because the compiler does not check that the result is valid.
|
||||
///
|
||||
/// Default: `false`
|
||||
///
|
||||
/// See <https://www.typescriptlang.org/tsconfig/#stripInternal>
|
||||
pub strip_internal: Option<bool>,
|
||||
|
||||
pub sourcemap: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<IsolatedDeclarationsOptions> for oxc::isolated_declarations::IsolatedDeclarationsOptions {
|
||||
fn from(options: IsolatedDeclarationsOptions) -> Self {
|
||||
Self { strip_internal: options.strip_internal.unwrap_or_default() }
|
||||
}
|
||||
}
|
||||
|
||||
/// TypeScript Isolated Declarations for Standalone DTS Emit
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
#[napi]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
mod errors;
|
||||
|
||||
pub use oxc_napi::{isolated_declarations, transform};
|
||||
|
||||
mod isolated_declaration;
|
||||
pub use isolated_declaration::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,396 @@
|
|||
use std::path::Path;
|
||||
// NOTE: Types must be aligned with [@types/babel__core](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b5dc32740d9b45d11cff9b025896dd333c795b39/types/babel__core/index.d.ts).
|
||||
#![allow(rustdoc::bare_urls)]
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use napi::Either;
|
||||
use napi_derive::napi;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use oxc::{
|
||||
codegen::CodegenReturn,
|
||||
diagnostics::OxcDiagnostic,
|
||||
isolated_declarations::IsolatedDeclarationsOptions,
|
||||
span::SourceType,
|
||||
transformer::{InjectGlobalVariablesConfig, InjectImport, ReplaceGlobalDefinesConfig},
|
||||
transformer::{
|
||||
EnvOptions, InjectGlobalVariablesConfig, InjectImport, JsxRuntime,
|
||||
ReplaceGlobalDefinesConfig, RewriteExtensionsMode,
|
||||
},
|
||||
CompilerInterface,
|
||||
};
|
||||
use oxc_napi::transform::{TransformOptions, TransformResult};
|
||||
use oxc_sourcemap::napi::SourceMap;
|
||||
|
||||
use crate::errors::wrap_diagnostics;
|
||||
use crate::{errors::wrap_diagnostics, IsolatedDeclarationsOptions};
|
||||
|
||||
#[derive(Default)]
|
||||
#[napi(object)]
|
||||
pub struct TransformResult {
|
||||
/// The transformed code.
|
||||
///
|
||||
/// If parsing failed, this will be an empty string.
|
||||
pub code: String,
|
||||
|
||||
/// The source map for the transformed code.
|
||||
///
|
||||
/// This will be set if {@link TransformOptions#sourcemap} is `true`.
|
||||
pub map: Option<SourceMap>,
|
||||
|
||||
/// The `.d.ts` declaration file for the transformed code. Declarations are
|
||||
/// only generated if `declaration` is set to `true` and a TypeScript file
|
||||
/// is provided.
|
||||
///
|
||||
/// If parsing failed and `declaration` is set, this will be an empty string.
|
||||
///
|
||||
/// @see {@link TypeScriptOptions#declaration}
|
||||
/// @see [declaration tsconfig option](https://www.typescriptlang.org/tsconfig/#declaration)
|
||||
pub declaration: Option<String>,
|
||||
|
||||
/// Declaration source map. Only generated if both
|
||||
/// {@link TypeScriptOptions#declaration declaration} and
|
||||
/// {@link TransformOptions#sourcemap sourcemap} are set to `true`.
|
||||
pub declaration_map: Option<SourceMap>,
|
||||
|
||||
/// Parse and transformation errors.
|
||||
///
|
||||
/// Oxc's parser recovers from common syntax errors, meaning that
|
||||
/// transformed code may still be available even if there are errors in this
|
||||
/// list.
|
||||
pub errors: Vec<String>,
|
||||
}
|
||||
|
||||
/// Options for transforming a JavaScript or TypeScript file.
|
||||
///
|
||||
/// @see {@link transform}
|
||||
#[napi(object)]
|
||||
#[derive(Default)]
|
||||
pub struct TransformOptions {
|
||||
#[napi(ts_type = "'script' | 'module' | 'unambiguous' | undefined")]
|
||||
pub source_type: Option<String>,
|
||||
|
||||
/// Treat the source text as `js`, `jsx`, `ts`, or `tsx`.
|
||||
#[napi(ts_type = "'js' | 'jsx' | 'ts' | 'tsx'")]
|
||||
pub lang: Option<String>,
|
||||
|
||||
/// The current working directory. Used to resolve relative paths in other
|
||||
/// options.
|
||||
pub cwd: Option<String>,
|
||||
|
||||
/// Enable source map generation.
|
||||
///
|
||||
/// When `true`, the `sourceMap` field of transform result objects will be populated.
|
||||
///
|
||||
/// @default false
|
||||
///
|
||||
/// @see {@link SourceMap}
|
||||
pub sourcemap: Option<bool>,
|
||||
|
||||
/// Set assumptions in order to produce smaller output.
|
||||
pub assumptions: Option<CompilerAssumptions>,
|
||||
|
||||
/// Configure how TypeScript is transformed.
|
||||
pub typescript: Option<TypeScriptOptions>,
|
||||
|
||||
/// Configure how TSX and JSX are transformed.
|
||||
pub jsx: Option<JsxOptions>,
|
||||
|
||||
/// Sets the target environment for the generated JavaScript.
|
||||
///
|
||||
/// The lowest target is `es2015`.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// * 'es2015'
|
||||
/// * ['es2020', 'chrome58', 'edge16', 'firefox57', 'node12', 'safari11']
|
||||
///
|
||||
/// @default `esnext` (No transformation)
|
||||
///
|
||||
/// @see [esbuild#target](https://esbuild.github.io/api/#target)
|
||||
pub target: Option<Either<String, Vec<String>>>,
|
||||
|
||||
/// Define Plugin
|
||||
#[napi(ts_type = "Record<string, string>")]
|
||||
pub define: Option<FxHashMap<String, String>>,
|
||||
|
||||
/// Inject Plugin
|
||||
#[napi(ts_type = "Record<string, string | [string, string]>")]
|
||||
pub inject: Option<FxHashMap<String, Either<String, Vec<String>>>>,
|
||||
}
|
||||
|
||||
impl TryFrom<TransformOptions> for oxc::transformer::TransformOptions {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(options: TransformOptions) -> Result<Self, Self::Error> {
|
||||
let env = match options.target {
|
||||
Some(Either::A(s)) => EnvOptions::from_target(&s)?,
|
||||
Some(Either::B(list)) => EnvOptions::from_target_list(&list)?,
|
||||
_ => EnvOptions::default(),
|
||||
};
|
||||
Ok(Self {
|
||||
cwd: options.cwd.map(PathBuf::from).unwrap_or_default(),
|
||||
assumptions: options.assumptions.map(Into::into).unwrap_or_default(),
|
||||
typescript: options
|
||||
.typescript
|
||||
.map(oxc::transformer::TypeScriptOptions::from)
|
||||
.unwrap_or_default(),
|
||||
jsx: options.jsx.map(Into::into).unwrap_or_default(),
|
||||
env,
|
||||
..Self::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct CompilerAssumptions {
|
||||
pub ignore_function_length: Option<bool>,
|
||||
pub no_document_all: Option<bool>,
|
||||
pub object_rest_no_symbols: Option<bool>,
|
||||
pub pure_getters: Option<bool>,
|
||||
pub set_public_class_fields: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<CompilerAssumptions> for oxc::transformer::CompilerAssumptions {
|
||||
fn from(value: CompilerAssumptions) -> Self {
|
||||
let ops = oxc::transformer::CompilerAssumptions::default();
|
||||
Self {
|
||||
ignore_function_length: value
|
||||
.ignore_function_length
|
||||
.unwrap_or(ops.ignore_function_length),
|
||||
no_document_all: value.no_document_all.unwrap_or(ops.no_document_all),
|
||||
object_rest_no_symbols: value
|
||||
.object_rest_no_symbols
|
||||
.unwrap_or(ops.object_rest_no_symbols),
|
||||
pure_getters: value.pure_getters.unwrap_or(ops.pure_getters),
|
||||
set_public_class_fields: value
|
||||
.set_public_class_fields
|
||||
.unwrap_or(ops.set_public_class_fields),
|
||||
..ops
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
#[derive(Default)]
|
||||
pub struct TypeScriptOptions {
|
||||
pub jsx_pragma: Option<String>,
|
||||
pub jsx_pragma_frag: Option<String>,
|
||||
pub only_remove_type_imports: Option<bool>,
|
||||
pub allow_namespaces: Option<bool>,
|
||||
pub allow_declare_fields: Option<bool>,
|
||||
/// Also generate a `.d.ts` declaration file for TypeScript files.
|
||||
///
|
||||
/// The source file must be compliant with all
|
||||
/// [`isolatedDeclarations`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#isolated-declarations)
|
||||
/// requirements.
|
||||
///
|
||||
/// @default false
|
||||
pub declaration: Option<IsolatedDeclarationsOptions>,
|
||||
/// Rewrite or remove TypeScript import/export declaration extensions.
|
||||
///
|
||||
/// - When set to `rewrite`, it will change `.ts`, `.mts`, `.cts` extensions to `.js`, `.mjs`, `.cjs` respectively.
|
||||
/// - When set to `remove`, it will remove `.ts`/`.mts`/`.cts`/`.tsx` extension entirely.
|
||||
/// - When set to `true`, it's equivalent to `rewrite`.
|
||||
/// - When set to `false` or omitted, no changes will be made to the extensions.
|
||||
///
|
||||
/// @default false
|
||||
#[napi(ts_type = "'rewrite' | 'remove' | boolean")]
|
||||
pub rewrite_import_extensions: Option<Either<bool, String>>,
|
||||
}
|
||||
|
||||
impl From<TypeScriptOptions> for oxc::transformer::TypeScriptOptions {
|
||||
fn from(options: TypeScriptOptions) -> Self {
|
||||
let ops = oxc::transformer::TypeScriptOptions::default();
|
||||
oxc::transformer::TypeScriptOptions {
|
||||
jsx_pragma: options.jsx_pragma.map(Into::into).unwrap_or(ops.jsx_pragma),
|
||||
jsx_pragma_frag: options.jsx_pragma_frag.map(Into::into).unwrap_or(ops.jsx_pragma_frag),
|
||||
only_remove_type_imports: options
|
||||
.only_remove_type_imports
|
||||
.unwrap_or(ops.only_remove_type_imports),
|
||||
allow_namespaces: options.allow_namespaces.unwrap_or(ops.allow_namespaces),
|
||||
allow_declare_fields: options.allow_declare_fields.unwrap_or(ops.allow_declare_fields),
|
||||
optimize_const_enums: false,
|
||||
rewrite_import_extensions: options.rewrite_import_extensions.and_then(|value| {
|
||||
match value {
|
||||
Either::A(v) => {
|
||||
if v {
|
||||
Some(RewriteExtensionsMode::Rewrite)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Either::B(v) => match v.as_str() {
|
||||
"rewrite" => Some(RewriteExtensionsMode::Rewrite),
|
||||
"remove" => Some(RewriteExtensionsMode::Remove),
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure how TSX and JSX are transformed.
|
||||
///
|
||||
/// @see {@link https://babeljs.io/docs/babel-plugin-transform-react-jsx#options}
|
||||
#[napi(object)]
|
||||
pub struct JsxOptions {
|
||||
/// Decides which runtime to use.
|
||||
///
|
||||
/// - 'automatic' - auto-import the correct JSX factories
|
||||
/// - 'classic' - no auto-import
|
||||
///
|
||||
/// @default 'automatic'
|
||||
#[napi(ts_type = "'classic' | 'automatic'")]
|
||||
pub runtime: Option<String>,
|
||||
|
||||
/// Emit development-specific information, such as `__source` and `__self`.
|
||||
///
|
||||
/// @default false
|
||||
///
|
||||
/// @see {@link https://babeljs.io/docs/babel-plugin-transform-react-jsx-development}
|
||||
pub development: Option<bool>,
|
||||
|
||||
/// Toggles whether or not to throw an error if an XML namespaced tag name
|
||||
/// is used.
|
||||
///
|
||||
/// Though the JSX spec allows this, it is disabled by default since React's
|
||||
/// JSX does not currently have support for it.
|
||||
///
|
||||
/// @default true
|
||||
pub throw_if_namespace: Option<bool>,
|
||||
|
||||
/// Enables `@babel/plugin-transform-react-pure-annotations`.
|
||||
///
|
||||
/// It will mark top-level React method calls as pure for tree shaking.
|
||||
///
|
||||
/// @see {@link https://babeljs.io/docs/en/babel-plugin-transform-react-pure-annotations}
|
||||
///
|
||||
/// @default true
|
||||
pub pure: Option<bool>,
|
||||
|
||||
/// Replaces the import source when importing functions.
|
||||
///
|
||||
/// @default 'react'
|
||||
pub import_source: Option<String>,
|
||||
|
||||
/// Replace the function used when compiling JSX expressions. It should be a
|
||||
/// qualified name (e.g. `React.createElement`) or an identifier (e.g.
|
||||
/// `createElement`).
|
||||
///
|
||||
/// Only used for `classic` {@link runtime}.
|
||||
///
|
||||
/// @default 'React.createElement'
|
||||
pub pragma: Option<String>,
|
||||
|
||||
/// Replace the component used when compiling JSX fragments. It should be a
|
||||
/// valid JSX tag name.
|
||||
///
|
||||
/// Only used for `classic` {@link runtime}.
|
||||
///
|
||||
/// @default 'React.Fragment'
|
||||
pub pragma_frag: Option<String>,
|
||||
|
||||
/// When spreading props, use `Object.assign` directly instead of an extend helper.
|
||||
///
|
||||
/// Only used for `classic` {@link runtime}.
|
||||
///
|
||||
/// @default false
|
||||
pub use_built_ins: Option<bool>,
|
||||
|
||||
/// When spreading props, use inline object with spread elements directly
|
||||
/// instead of an extend helper or Object.assign.
|
||||
///
|
||||
/// Only used for `classic` {@link runtime}.
|
||||
///
|
||||
/// @default false
|
||||
pub use_spread: Option<bool>,
|
||||
|
||||
/// Enable React Fast Refresh .
|
||||
///
|
||||
/// Conforms to the implementation in {@link https://github.com/facebook/react/tree/v18.3.1/packages/react-refresh}
|
||||
///
|
||||
/// @default false
|
||||
pub refresh: Option<Either<bool, ReactRefreshOptions>>,
|
||||
}
|
||||
|
||||
impl From<JsxOptions> for oxc::transformer::JsxOptions {
|
||||
fn from(options: JsxOptions) -> Self {
|
||||
let ops = oxc::transformer::JsxOptions::default();
|
||||
oxc::transformer::JsxOptions {
|
||||
runtime: match options.runtime.as_deref() {
|
||||
Some("classic") => JsxRuntime::Classic,
|
||||
/* "automatic" */ _ => JsxRuntime::Automatic,
|
||||
},
|
||||
development: options.development.unwrap_or(ops.development),
|
||||
throw_if_namespace: options.throw_if_namespace.unwrap_or(ops.throw_if_namespace),
|
||||
pure: options.pure.unwrap_or(ops.pure),
|
||||
import_source: options.import_source,
|
||||
pragma: options.pragma,
|
||||
pragma_frag: options.pragma_frag,
|
||||
use_built_ins: options.use_built_ins,
|
||||
use_spread: options.use_spread,
|
||||
refresh: options.refresh.and_then(|value| match value {
|
||||
Either::A(b) => b.then(oxc::transformer::ReactRefreshOptions::default),
|
||||
Either::B(options) => Some(oxc::transformer::ReactRefreshOptions::from(options)),
|
||||
}),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ReactRefreshOptions {
|
||||
/// Specify the identifier of the refresh registration variable.
|
||||
///
|
||||
/// @default `$RefreshReg$`.
|
||||
pub refresh_reg: Option<String>,
|
||||
|
||||
/// Specify the identifier of the refresh signature variable.
|
||||
///
|
||||
/// @default `$RefreshSig$`.
|
||||
pub refresh_sig: Option<String>,
|
||||
|
||||
pub emit_full_signatures: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<ReactRefreshOptions> for oxc::transformer::ReactRefreshOptions {
|
||||
fn from(options: ReactRefreshOptions) -> Self {
|
||||
let ops = oxc::transformer::ReactRefreshOptions::default();
|
||||
oxc::transformer::ReactRefreshOptions {
|
||||
refresh_reg: options.refresh_reg.unwrap_or(ops.refresh_reg),
|
||||
refresh_sig: options.refresh_sig.unwrap_or(ops.refresh_sig),
|
||||
emit_full_signatures: options.emit_full_signatures.unwrap_or(ops.emit_full_signatures),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct ArrowFunctionsOptions {
|
||||
/// This option enables the following:
|
||||
/// * Wrap the generated function in .bind(this) and keeps uses of this inside the function as-is, instead of using a renamed this.
|
||||
/// * Add a runtime check to ensure the functions are not instantiated.
|
||||
/// * Add names to arrow functions.
|
||||
///
|
||||
/// @default false
|
||||
pub spec: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<ArrowFunctionsOptions> for oxc::transformer::ArrowFunctionsOptions {
|
||||
fn from(options: ArrowFunctionsOptions) -> Self {
|
||||
oxc::transformer::ArrowFunctionsOptions { spec: options.spec.unwrap_or_default() }
|
||||
}
|
||||
}
|
||||
|
||||
#[napi(object)]
|
||||
pub struct Es2015Options {
|
||||
/// Transform arrow functions into function expressions.
|
||||
pub arrow_function: Option<ArrowFunctionsOptions>,
|
||||
}
|
||||
|
||||
impl From<Es2015Options> for oxc::transformer::ES2015Options {
|
||||
fn from(options: Es2015Options) -> Self {
|
||||
oxc::transformer::ES2015Options { arrow_function: options.arrow_function.map(Into::into) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Compiler {
|
||||
|
|
@ -116,7 +492,9 @@ impl CompilerInterface for Compiler {
|
|||
Some(&self.transform_options)
|
||||
}
|
||||
|
||||
fn isolated_declaration_options(&self) -> Option<IsolatedDeclarationsOptions> {
|
||||
fn isolated_declaration_options(
|
||||
&self,
|
||||
) -> Option<oxc::isolated_declarations::IsolatedDeclarationsOptions> {
|
||||
self.isolated_declaration_options
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"build": "pnpm --workspace-concurrency=1 --filter './napi/*' build",
|
||||
"build-dev": "pnpm --workspace-concurrency=1 --filter './napi/*' build-dev",
|
||||
"test": "pnpm --workspace-concurrency=1 --filter './napi/*' test"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue