Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(es): Add an option to disable builtin transforms #7873

Merged
merged 10 commits into from
Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 85 additions & 78 deletions crates/swc/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ impl Options {
config: Option<Config>,
comments: Option<&'a SingleThreadedComments>,
custom_before_pass: impl FnOnce(&Program) -> P,
) -> Result<BuiltInput<impl 'a + swc_ecma_visit::Fold>, Error>
) -> Result<BuiltInput<Box<dyn 'a + Fold>>, Error>
where
P: 'a + swc_ecma_visit::Fold,
{
Expand Down Expand Up @@ -759,88 +759,92 @@ impl Options {
noop()
};

let pass = chain!(
lint_to_fold(swc_ecma_lints::rules::all(LintParams {
program: &program,
lint_config: &lints,
top_level_ctxt,
unresolved_ctxt,
es_version,
source_map: cm.clone(),
})),
// Decorators may use type information
Optional::new(
match transform.decorator_version.unwrap_or_default() {
DecoratorVersion::V202112 => {
Either::Left(decorators(decorators::Config {
legacy: transform.legacy_decorator.into_bool(),
emit_metadata: transform.decorator_metadata.into_bool(),
use_define_for_class_fields: !assumptions.set_public_class_fields,
}))
}
DecoratorVersion::V202203 => {
Either::Right(
let pass: Box<dyn Fold> = if experimental.disable_builtin_transforms.into_bool() {
Box::new(plugin_transforms)
} else {
Box::new(chain!(
lint_to_fold(swc_ecma_lints::rules::all(LintParams {
program: &program,
lint_config: &lints,
top_level_ctxt,
unresolved_ctxt,
es_version,
source_map: cm.clone(),
})),
// Decorators may use type information
Optional::new(
match transform.decorator_version.unwrap_or_default() {
DecoratorVersion::V202112 => {
Either::Left(decorators(decorators::Config {
legacy: transform.legacy_decorator.into_bool(),
emit_metadata: transform.decorator_metadata.into_bool(),
use_define_for_class_fields: !assumptions.set_public_class_fields,
}))
}
DecoratorVersion::V202203 => {
Either::Right(
swc_ecma_transforms::proposals::decorator_2022_03::decorator_2022_03(),
)
}
},
syntax.decorators()
),
// The transform strips import assertions, so it's only enabled if
// keep_import_assertions is false.
Optional::new(import_assertions(), !keep_import_assertions),
Optional::new(
typescript::strip_with_jsx::<Option<&dyn Comments>>(
cm.clone(),
typescript::Config {
pragma: Some(
transform
.react
.pragma
.clone()
.unwrap_or_else(default_pragma)
),
pragma_frag: Some(
transform
.react
.pragma_frag
.clone()
.unwrap_or_else(default_pragma_frag)
),
ts_enum_config: TsEnumConfig {
treat_const_enum_as_enum: transform
.treat_const_enum_as_enum
.into_bool(),
ts_enum_is_readonly: assumptions.ts_enum_is_readonly,
},
import_export_assign_config,
..Default::default()
}
},
comments.map(|v| v as _),
top_level_mark
syntax.decorators()
),
syntax.typescript()
),
plugin_transforms,
custom_before_pass(&program),
// handle jsx
Optional::new(
react::react::<&dyn Comments>(
cm.clone(),
comments.map(|v| v as _),
transform.react,
top_level_mark,
unresolved_mark
// The transform strips import assertions, so it's only enabled if
// keep_import_assertions is false.
Optional::new(import_assertions(), !keep_import_assertions),
Optional::new(
typescript::strip_with_jsx::<Option<&dyn Comments>>(
cm.clone(),
typescript::Config {
pragma: Some(
transform
.react
.pragma
.clone()
.unwrap_or_else(default_pragma)
),
pragma_frag: Some(
transform
.react
.pragma_frag
.clone()
.unwrap_or_else(default_pragma_frag)
),
ts_enum_config: TsEnumConfig {
treat_const_enum_as_enum: transform
.treat_const_enum_as_enum
.into_bool(),
ts_enum_is_readonly: assumptions.ts_enum_is_readonly,
},
import_export_assign_config,
..Default::default()
},
comments.map(|v| v as _),
top_level_mark
),
syntax.typescript()
),
syntax.jsx()
),
pass,
Optional::new(jest::jest(), transform.hidden.jest.into_bool()),
Optional::new(
dropped_comments_preserver(comments.cloned()),
preserve_all_comments
),
);
plugin_transforms,
custom_before_pass(&program),
// handle jsx
Optional::new(
react::react::<&dyn Comments>(
cm.clone(),
comments.map(|v| v as _),
transform.react,
top_level_mark,
unresolved_mark
),
syntax.jsx()
),
pass,
Optional::new(jest::jest(), transform.hidden.jest.into_bool()),
Optional::new(
dropped_comments_preserver(comments.cloned()),
preserve_all_comments
),
))
};

Ok(BuiltInput {
program,
Expand Down Expand Up @@ -1454,6 +1458,9 @@ pub struct JscExperimental {
/// and will not be considered as breaking changes.
#[serde(default)]
pub cache_root: Option<String>,

#[serde(default)]
pub disable_builtin_transforms: BoolConfig<false>,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
Expand Down
22 changes: 11 additions & 11 deletions crates/swc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ impl Compiler {
}
}

#[tracing::instrument(level = "info", skip_all)]
#[tracing::instrument(skip_all)]
pub fn read_config(&self, opts: &Options, name: &FileName) -> Result<Option<Config>, Error> {
static CUR_DIR: Lazy<PathBuf> = Lazy::new(|| {
if cfg!(target_arch = "wasm32") {
Expand Down Expand Up @@ -845,7 +845,7 @@ impl Compiler {
/// This method handles merging of config.
///
/// This method does **not** parse module.
#[tracing::instrument(level = "info", skip_all)]
#[tracing::instrument(skip_all)]
pub fn parse_js_as_input<'a, P>(
&'a self,
fm: Lrc<SourceFile>,
Expand Down Expand Up @@ -908,7 +908,7 @@ impl Compiler {
})
}

#[tracing::instrument(level = "info", skip_all)]
#[tracing::instrument(skip_all)]
pub fn transform(
&self,
handler: &Handler,
Expand Down Expand Up @@ -936,7 +936,7 @@ impl Compiler {
///
/// This means, you can use `noop_visit_type`, `noop_fold_type` and
/// `noop_visit_mut_type` in your visitor to reduce the binary size.
#[tracing::instrument(level = "info", skip_all)]
#[tracing::instrument(skip_all)]
pub fn process_js_with_custom_pass<P1, P2>(
&self,
fm: Arc<SourceFile>,
Expand Down Expand Up @@ -997,11 +997,11 @@ impl Compiler {
None
};

self.process_js_inner(handler, orig.as_ref(), config)
self.apply_transforms(handler, orig.as_ref(), config)
})
}

#[tracing::instrument(level = "info", skip(self, handler, opts))]
#[tracing::instrument(skip(self, handler, opts))]
pub fn process_js_file(
&self,
fm: Arc<SourceFile>,
Expand All @@ -1019,7 +1019,7 @@ impl Compiler {
)
}

#[tracing::instrument(level = "info", skip_all)]
#[tracing::instrument(skip_all)]
pub fn minify(
&self,
fm: Arc<SourceFile>,
Expand Down Expand Up @@ -1186,7 +1186,7 @@ impl Compiler {
/// You can use custom pass with this method.
///
/// There exists a [PassBuilder] to help building custom passes.
#[tracing::instrument(level = "info", skip_all)]
#[tracing::instrument(skip_all)]
pub fn process_js(
&self,
handler: &Handler,
Expand All @@ -1207,8 +1207,8 @@ impl Compiler {
)
}

#[tracing::instrument(level = "info", skip_all)]
fn process_js_inner(
#[tracing::instrument(name = "swc::Compiler::apply_transforms", skip_all)]
fn apply_transforms(
&self,
handler: &Handler,
orig: Option<&sourcemap::SourceMap>,
Expand Down Expand Up @@ -1281,7 +1281,7 @@ fn find_swcrc(path: &Path, root: &Path, root_mode: RootMode) -> Option<PathBuf>
None
}

#[tracing::instrument(level = "info", skip_all)]
#[tracing::instrument(skip_all)]
fn load_swcrc(path: &Path) -> Result<Rc, Error> {
let content = read_to_string(path).context("failed to read config (.swcrc) file")?;

Expand Down
31 changes: 31 additions & 0 deletions node-swc/__tests__/transform/experimental.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import swc from "../../..";

describe("when jsc.experimentalDisableBuiltinTransforms is true", () => {
it("should preserve TypeScript", async () => {
const { code } = await swc.transform(
`
const hello: Type = () => {
console.log('hello');
};
`,
{
jsc: {
parser: {
syntax: "typescript",
},
experimental: {
disableBuiltinTransforms: true,
},
},
minify: false,
}
);

expect(code).toMatchInlineSnapshot(`
"const hello: Type = ()=>{
console.log(\\"hello\\");
};
"
`);
});
});