From d2929d1ce61a00360cc0596441041571a958da23 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Wed, 14 Aug 2024 08:11:04 +0800 Subject: [PATCH] feat(es/typescript): Add `native_class_properties ` to skip reordering of class properties inits (#9421) **Related issue:** - Closes #9418 --- .changeset/neat-humans-reply.md | 7 +++ crates/swc_ecma_transforms/tests/deno.rs | 1 + .../src/config.rs | 6 +++ .../src/transform.rs | 49 ++++++++++++++++++- .../src/typescript.rs | 1 + crates/swc_fast_ts_strip/src/lib.rs | 21 ++++++++ crates/swc_fast_ts_strip/tests/fixture.rs | 4 ++ .../tests/fixture/class-properties.js | 6 +++ .../tests/fixture/class-properties.swc-stderr | 7 +++ .../fixture/class-properties.transform.js | 8 +++ .../tests/fixture/class-properties.ts | 6 +++ 11 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 .changeset/neat-humans-reply.md create mode 100644 crates/swc_fast_ts_strip/tests/fixture/class-properties.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/class-properties.swc-stderr create mode 100644 crates/swc_fast_ts_strip/tests/fixture/class-properties.transform.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/class-properties.ts diff --git a/.changeset/neat-humans-reply.md b/.changeset/neat-humans-reply.md new file mode 100644 index 000000000000..1cc5896a3f75 --- /dev/null +++ b/.changeset/neat-humans-reply.md @@ -0,0 +1,7 @@ +--- +swc_core: patch +swc_fast_ts_strip: patch +swc_ecma_transforms_typescript: minor +--- + +feat(es/typescript): Add `native_class_properties ` to skip reordering of class properties inits diff --git a/crates/swc_ecma_transforms/tests/deno.rs b/crates/swc_ecma_transforms/tests/deno.rs index 6d1573dd40f6..4b00541d3078 100644 --- a/crates/swc_ecma_transforms/tests/deno.rs +++ b/crates/swc_ecma_transforms/tests/deno.rs @@ -36,6 +36,7 @@ fn run_test(input: PathBuf) { typescript( typescript::Config { verbatim_module_syntax: false, + native_class_properties: false, import_not_used_as_values: typescript::ImportsNotUsedAsValues::Remove, no_empty_export: true, import_export_assign_config: diff --git a/crates/swc_ecma_transforms_typescript/src/config.rs b/crates/swc_ecma_transforms_typescript/src/config.rs index d04c0e3e88fe..63fac10a65a8 100644 --- a/crates/swc_ecma_transforms_typescript/src/config.rs +++ b/crates/swc_ecma_transforms_typescript/src/config.rs @@ -3,9 +3,15 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Config { + /// https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax #[serde(default)] pub verbatim_module_syntax: bool, + /// Native class properties support + #[serde(default)] + pub native_class_properties: bool, + + /// https://www.typescriptlang.org/tsconfig/#importsNotUsedAsValues #[serde(default)] pub import_not_used_as_values: ImportsNotUsedAsValues, diff --git a/crates/swc_ecma_transforms_typescript/src/transform.rs b/crates/swc_ecma_transforms_typescript/src/transform.rs index 91720cdfb902..0264857cc022 100644 --- a/crates/swc_ecma_transforms_typescript/src/transform.rs +++ b/crates/swc_ecma_transforms_typescript/src/transform.rs @@ -59,6 +59,7 @@ pub(crate) struct Transform { import_export_assign_config: TsImportExportAssignConfig, ts_enum_is_mutable: bool, verbatim_module_syntax: bool, + native_class_properties: bool, namespace_id: Option, record: TsEnumRecord, @@ -74,6 +75,7 @@ pub fn transform( import_export_assign_config: TsImportExportAssignConfig, ts_enum_is_mutable: bool, verbatim_module_syntax: bool, + native_class_properties: bool, ) -> impl Fold + VisitMut { as_folder(Transform { unresolved_mark, @@ -82,6 +84,7 @@ pub fn transform( import_export_assign_config, ts_enum_is_mutable, verbatim_module_syntax, + native_class_properties, ..Default::default() }) } @@ -139,7 +142,11 @@ impl VisitMut for Transform { let init_list = mem::replace(&mut self.in_class_prop_init, init_list); if !prop_list.is_empty() { - self.reorder_class_prop_decls(n, prop_list, init_list); + if self.native_class_properties { + self.reorder_class_prop_decls(n, prop_list, init_list); + } else { + self.reorder_class_prop_decls_and_inits(n, prop_list, init_list); + } } } @@ -728,7 +735,7 @@ impl Transform { } impl Transform { - fn reorder_class_prop_decls( + fn reorder_class_prop_decls_and_inits( &mut self, class_member_list: &mut Vec, prop_list: Vec, @@ -829,6 +836,44 @@ impl Transform { .map(ClassMember::ClassProp), ); } + + fn reorder_class_prop_decls( + &mut self, + class_member_list: &mut Vec, + prop_list: Vec, + init_list: Vec>, + ) { + if let Some(constructor) = class_member_list + .iter_mut() + .find_map(|m| m.as_mut_constructor()) + { + inject_after_super(constructor, init_list); + } + + class_member_list.splice( + 0..0, + prop_list + .into_iter() + .map(Ident::from) + .map(PropName::from) + .map(|key| ClassProp { + span: DUMMY_SP, + key, + value: None, + type_ann: None, + is_static: false, + decorators: Vec::new(), + accessibility: None, + is_abstract: false, + is_optional: false, + is_override: false, + readonly: false, + declare: false, + definite: false, + }) + .map(ClassMember::ClassProp), + ); + } } impl Transform { diff --git a/crates/swc_ecma_transforms_typescript/src/typescript.rs b/crates/swc_ecma_transforms_typescript/src/typescript.rs index e9b161749784..ed3c51844630 100644 --- a/crates/swc_ecma_transforms_typescript/src/typescript.rs +++ b/crates/swc_ecma_transforms_typescript/src/typescript.rs @@ -57,6 +57,7 @@ impl VisitMut for TypeScript { self.config.import_export_assign_config, self.config.ts_enum_is_mutable, self.config.verbatim_module_syntax, + self.config.native_class_properties, )); if let Some(span) = was_module { diff --git a/crates/swc_fast_ts_strip/src/lib.rs b/crates/swc_fast_ts_strip/src/lib.rs index d67bfd499a82..3ac51046b9b4 100644 --- a/crates/swc_fast_ts_strip/src/lib.rs +++ b/crates/swc_fast_ts_strip/src/lib.rs @@ -69,10 +69,31 @@ interface Options { } interface TransformConfig { + /** + * @see https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax + */ verbatimModuleSyntax?: boolean; + /** + * Native class properties support + */ + nativeClassProperties?: boolean; importNotUsedAsValues?: "remove" | "preserve"; + /** + * Don't create `export {}`. + * By default, strip creates `export {}` for modules to preserve module + * context. + * + * @see /~https://github.com/swc-project/swc/issues/1698 + */ noEmptyExport?: boolean; importExportAssignConfig?: "Classic" | "Preserve" | "NodeNext" | "EsNext"; + /** + * Disables an optimization that inlines TS enum member values + * within the same module that assumes the enum member values + * are never modified. + * + * Defaults to false. + */ tsEnumIsMutable?: boolean; } "#; diff --git a/crates/swc_fast_ts_strip/tests/fixture.rs b/crates/swc_fast_ts_strip/tests/fixture.rs index 9c54bb131bbe..9f537e35c98e 100644 --- a/crates/swc_fast_ts_strip/tests/fixture.rs +++ b/crates/swc_fast_ts_strip/tests/fixture.rs @@ -120,6 +120,10 @@ fn opts(mode: Mode) -> Options { ..Default::default() }, mode, + transform: Some(swc_ecma_transforms_typescript::Config { + native_class_properties: true, + ..Default::default() + }), ..Default::default() } } diff --git a/crates/swc_fast_ts_strip/tests/fixture/class-properties.js b/crates/swc_fast_ts_strip/tests/fixture/class-properties.js new file mode 100644 index 000000000000..3713bda1fc69 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/class-properties.js @@ -0,0 +1,6 @@ +class Foo { + x = console.log(1) + constructor(public y = console.log(2)) { + console.log(3) + } +} \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/class-properties.swc-stderr b/crates/swc_fast_ts_strip/tests/fixture/class-properties.swc-stderr new file mode 100644 index 000000000000..82c4bf1c5f6c --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/class-properties.swc-stderr @@ -0,0 +1,7 @@ + x TypeScript parameter property is not supported in strip-only mode + ,-[3:1] + 2 | x = console.log(1) + 3 | constructor(public y = console.log(2)) { + : ^^^^^^^^^^^^^^^^^^ + 4 | console.log(3) + `---- diff --git a/crates/swc_fast_ts_strip/tests/fixture/class-properties.transform.js b/crates/swc_fast_ts_strip/tests/fixture/class-properties.transform.js new file mode 100644 index 000000000000..a81424c21aa4 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/class-properties.transform.js @@ -0,0 +1,8 @@ +class Foo { + y; + x = console.log(1); + constructor(y = console.log(2)){ + this.y = y; + console.log(3); + } +} diff --git a/crates/swc_fast_ts_strip/tests/fixture/class-properties.ts b/crates/swc_fast_ts_strip/tests/fixture/class-properties.ts new file mode 100644 index 000000000000..3713bda1fc69 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/class-properties.ts @@ -0,0 +1,6 @@ +class Foo { + x = console.log(1) + constructor(public y = console.log(2)) { + console.log(3) + } +} \ No newline at end of file