From b129343c949c43c0ad3eb4ad4676e75dc37067e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Fri, 5 Jul 2024 21:07:24 +0900 Subject: [PATCH] feat(es/typescript): Add `swc_fast_ts_strip` (#9143) **Description:** This PR also adds a CI process for each Wasm binding. --------- Co-authored-by: magic-akari --- .github/workflows/CI.yml | 12 +- Cargo.lock | 13 + Cargo.toml | 1 + bindings/Cargo.lock | 118 +++------ .../__tests__/__snapshots__/simple.js.snap | 7 + .../binding_minifier_wasm/__tests__/simple.js | 15 ++ .../binding_minifier_wasm/scripts/test.sh | 6 + bindings/binding_typescript_wasm/Cargo.toml | 13 +- .../__tests__/__snapshots__/transform.js.snap | 75 +++++- .../__tests__/transform.js | 116 +++++++- bindings/binding_typescript_wasm/src/lib.rs | 250 +----------------- .../tests/decorator-tests | 2 +- crates/swc_fast_ts_strip/Cargo.toml | 23 ++ crates/swc_fast_ts_strip/src/lib.rs | 245 +++++++++++++++++ .../tests/errors/decorators.swc-stderr | 5 + .../tests/errors/decorators.ts | 1 + .../tests/errors/enums.swc-stderr | 5 + .../swc_fast_ts_strip/tests/errors/enums.ts | 1 + .../tests/errors/modules.swc-stderr | 5 + .../swc_fast_ts_strip/tests/errors/modules.ts | 1 + .../tests/errors/namespaces.swc-stderr | 5 + .../tests/errors/namespaces.ts | 1 + crates/swc_fast_ts_strip/tests/fixture.rs | 48 ++++ .../tests/fixture/const-assertion.js | 3 + .../tests/fixture/const-assertion.ts | 3 + .../tests/fixture/declare-enum/empty.js | 1 + .../tests/fixture/declare-enum/empty.ts | 1 + .../tests/fixture/declare-enum/simple.js | 1 + .../tests/fixture/declare-enum/simple.ts | 3 + .../tests/fixture/declare-enum/with-init.js | 1 + .../tests/fixture/declare-enum/with-init.ts | 4 + .../tests/fixture/instantiation-expr.js | 3 + .../tests/fixture/instantiation-expr.ts | 3 + .../tests/fixture/mixed/1.js | 6 + .../tests/fixture/mixed/1.ts | 6 + .../tests/fixture/nonnull-assertion/1.js | 2 + .../tests/fixture/nonnull-assertion/1.ts | 2 + .../tests/fixture/pat-optional.js | 9 + .../tests/fixture/pat-optional.ts | 9 + .../tests/fixture/satisfies/1.js | 2 + .../tests/fixture/satisfies/1.ts | 2 + .../tests/fixture/this-param.js | 2 + .../tests/fixture/this-param.ts | 2 + .../tests/fixture/type-alias/1.js | 2 + .../tests/fixture/type-alias/1.ts | 2 + .../tests/fixture/type-alias/2.js | 4 + .../tests/fixture/type-alias/2.ts | 4 + .../tests/fixture/type-ann/var-decl/1.js | 2 + .../tests/fixture/type-ann/var-decl/1.ts | 2 + .../tests/fixture/type-assertions/1.js | 2 + .../tests/fixture/type-assertions/1.ts | 2 + 51 files changed, 689 insertions(+), 364 deletions(-) create mode 100644 bindings/binding_minifier_wasm/__tests__/__snapshots__/simple.js.snap create mode 100644 bindings/binding_minifier_wasm/__tests__/simple.js create mode 100755 bindings/binding_minifier_wasm/scripts/test.sh create mode 100644 crates/swc_fast_ts_strip/Cargo.toml create mode 100644 crates/swc_fast_ts_strip/src/lib.rs create mode 100644 crates/swc_fast_ts_strip/tests/errors/decorators.swc-stderr create mode 100644 crates/swc_fast_ts_strip/tests/errors/decorators.ts create mode 100644 crates/swc_fast_ts_strip/tests/errors/enums.swc-stderr create mode 100644 crates/swc_fast_ts_strip/tests/errors/enums.ts create mode 100644 crates/swc_fast_ts_strip/tests/errors/modules.swc-stderr create mode 100644 crates/swc_fast_ts_strip/tests/errors/modules.ts create mode 100644 crates/swc_fast_ts_strip/tests/errors/namespaces.swc-stderr create mode 100644 crates/swc_fast_ts_strip/tests/errors/namespaces.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture.rs create mode 100644 crates/swc_fast_ts_strip/tests/fixture/const-assertion.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/const-assertion.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/declare-enum/empty.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/declare-enum/empty.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/declare-enum/simple.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/declare-enum/simple.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/declare-enum/with-init.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/declare-enum/with-init.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/instantiation-expr.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/instantiation-expr.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/mixed/1.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/mixed/1.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/nonnull-assertion/1.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/nonnull-assertion/1.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/pat-optional.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/pat-optional.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/satisfies/1.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/satisfies/1.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/this-param.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/this-param.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/type-alias/1.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/type-alias/1.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/type-alias/2.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/type-alias/2.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/type-ann/var-decl/1.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/type-ann/var-decl/1.ts create mode 100644 crates/swc_fast_ts_strip/tests/fixture/type-assertions/1.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/type-assertions/1.ts diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 43b0fec2ec11..48fff44c955c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -166,6 +166,14 @@ jobs: if: >- ${{ !contains(github.event.head_commit.message, 'chore: ') }} runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + pkg: + - binding_core_wasm + - binding_minifier_wasm + - binding_typescript_wasm + steps: - uses: actions/checkout@v4 @@ -200,7 +208,7 @@ jobs: - name: Test run: | - (cd bindings/binding_core_wasm && ./scripts/test.sh) + (cd bindings/${{ matrix.pkg }} && ./scripts/test.sh) cargo-test: name: Test - ${{ matrix.settings.crate }} - ${{ matrix.settings.os }} @@ -460,6 +468,8 @@ jobs: runner: ubuntu-latest - crate: swc_fast_graph os: ubuntu-latest + - crate: swc_fast_ts_strip + os: ubuntu-latest runner: ubuntu-latest - crate: swc_graph_analyzer os: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index e1aca73ac297..888603dcfe13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4904,6 +4904,19 @@ dependencies = [ "swc_common", ] +[[package]] +name = "swc_fast_ts_strip" +version = "0.1.1" +dependencies = [ + "anyhow", + "serde", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "swc_ecma_visit", + "testing", +] + [[package]] name = "swc_graph_analyzer" version = "0.23.0" diff --git a/Cargo.toml b/Cargo.toml index d22e2e0c2040..5f104a01c8a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ members = [ "crates/swc_x_optimizer", "crates/swc_transform_common", "crates/swc_typescript", + "crates/swc_fast_ts_strip", ] resolver = "2" diff --git a/bindings/Cargo.lock b/bindings/Cargo.lock index 333dd566bbd3..c9b4cba39fbf 100644 --- a/bindings/Cargo.lock +++ b/bindings/Cargo.lock @@ -311,9 +311,9 @@ dependencies = [ "serde", "serde-wasm-bindgen", "serde_json", - "swc_core", - "swc_ecma_codegen", + "swc_common", "swc_error_reporters", + "swc_fast_ts_strip", "tracing", "wasm-bindgen", "wasm-bindgen-futures", @@ -465,8 +465,8 @@ dependencies = [ "once_cell", "strsim", "termcolor", - "terminal_size 0.2.6", - "textwrap 0.16.0", + "terminal_size", + "textwrap", ] [[package]] @@ -1480,12 +1480,6 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "is_ci" -version = "1.1.1" -source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" - [[package]] name = "itertools" version = "0.13.0" @@ -1682,33 +1676,27 @@ dependencies = [ [[package]] name = "miette" -version = "4.7.1" +version = "7.2.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "1c90329e44f9208b55f45711f9558cec15d7ef8295cc65ecd6d4188ae8edc58c" +checksum = "4edc8853320c2a0dab800fbda86253c8938f6ea88510dc92c5f1ed20e794afc1" dependencies = [ - "atty", - "backtrace", + "cfg-if", "miette-derive", - "once_cell", "owo-colors", - "supports-color", - "supports-hyperlinks", - "supports-unicode", - "terminal_size 0.1.17", - "textwrap 0.15.2", + "textwrap", "thiserror", "unicode-width", ] [[package]] name = "miette-derive" -version = "4.7.1" +version = "7.2.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "6b5bc45b761bcf1b5e6e6c4128cd93b84c218721a8d9b894aa0aff4ed180174c" +checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -1976,9 +1964,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owo-colors" -version = "3.5.0" +version = "4.0.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f" [[package]] name = "parking_lot" @@ -2893,34 +2881,6 @@ version = "2.4.1" source = "registry+/~https://github.com/rust-lang/crates.io-index" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" -[[package]] -name = "supports-color" -version = "1.3.1" -source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "8ba6faf2ca7ee42fdd458f4347ae0a9bd6bcc445ad7cb57ad82b383f18870d6f" -dependencies = [ - "atty", - "is_ci", -] - -[[package]] -name = "supports-hyperlinks" -version = "1.2.0" -source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "590b34f7c5f01ecc9d78dba4b3f445f31df750a67621cf31626f3b7441ce6406" -dependencies = [ - "atty", -] - -[[package]] -name = "supports-unicode" -version = "1.0.2" -source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "a8b945e45b417b125a8ec51f1b7df2f8df7920367700d1f98aedd21e5735f8b2" -dependencies = [ - "atty", -] - [[package]] name = "swc" version = "0.279.0" @@ -3170,7 +3130,6 @@ dependencies = [ "swc_ecma_minifier", "swc_ecma_parser", "swc_ecma_transforms_base", - "swc_ecma_transforms_typescript", "swc_ecma_visit", "swc_malloc", "swc_node_bundler", @@ -3850,9 +3809,9 @@ dependencies = [ [[package]] name = "swc_error_reporters" -version = "0.18.0" +version = "0.18.1" source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "9bd8f9a90efb59dc5d918b4470e5d152f34cac2f8733bfba141a96440cab3eff" +checksum = "4689d9bb6092b5e6a0b79c0152336a8bd7f0acaf70dcf4133f86deb01775baa0" dependencies = [ "anyhow", "miette", @@ -3873,6 +3832,17 @@ dependencies = [ "swc_common", ] +[[package]] +name = "swc_fast_ts_strip" +version = "0.1.1" +source = "registry+/~https://github.com/rust-lang/crates.io-index" +checksum = "8b318927847fba58352647cf78ee30edfe25d160b5ee9b43c1456b27a181d575" +dependencies = [ + "anyhow", + "serde", + "swc_core", +] + [[package]] name = "swc_graph_analyzer" version = "0.23.0" @@ -4145,16 +4115,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "terminal_size" -version = "0.1.17" -source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "terminal_size" version = "0.2.6" @@ -4176,38 +4136,30 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.2" +version = "0.16.0" source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" dependencies = [ "smawk", + "terminal_size", "unicode-linebreak", "unicode-width", ] -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" -dependencies = [ - "terminal_size 0.2.6", -] - [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.61" source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.61" source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", @@ -4538,9 +4490,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.13" source = "registry+/~https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" diff --git a/bindings/binding_minifier_wasm/__tests__/__snapshots__/simple.js.snap b/bindings/binding_minifier_wasm/__tests__/__snapshots__/simple.js.snap new file mode 100644 index 000000000000..6fa89d2dee78 --- /dev/null +++ b/bindings/binding_minifier_wasm/__tests__/__snapshots__/simple.js.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`minify should work 1`] = ` +Object { + "code": "console.log(1);", +} +`; diff --git a/bindings/binding_minifier_wasm/__tests__/simple.js b/bindings/binding_minifier_wasm/__tests__/simple.js new file mode 100644 index 000000000000..b642c713ec17 --- /dev/null +++ b/bindings/binding_minifier_wasm/__tests__/simple.js @@ -0,0 +1,15 @@ +const swc = require("../pkg"); + +describe("minify", () => { + it("should work", async () => { + const output = await swc.minify( + `{ + const a = 1; + console.log(a); + }`, + {} + ); + + expect(output).toMatchSnapshot(); + }); +}); diff --git a/bindings/binding_minifier_wasm/scripts/test.sh b/bindings/binding_minifier_wasm/scripts/test.sh new file mode 100755 index 000000000000..dcc3fb682ba1 --- /dev/null +++ b/bindings/binding_minifier_wasm/scripts/test.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -eu + +wasm-pack build --out-name wasm --release --scope=swc --target nodejs +npx jest $@ \ No newline at end of file diff --git a/bindings/binding_typescript_wasm/Cargo.toml b/bindings/binding_typescript_wasm/Cargo.toml index 1083dbc20646..1b3a21ded08f 100644 --- a/bindings/binding_typescript_wasm/Cargo.toml +++ b/bindings/binding_typescript_wasm/Cargo.toml @@ -20,18 +20,9 @@ getrandom = { version = "0.2.10", features = ["js"] } serde = { version = "1", features = ["derive"] } serde-wasm-bindgen = "0.4.5" serde_json = "1.0.120" -swc_core = { version = "0.96.3", features = [ - "common", - "common_sourcemap", - "ecma_ast", - "ecma_codegen", - "ecma_parser", - "ecma_transforms", - "ecma_transforms_typescript", - "ecma_visit", -] } -swc_ecma_codegen = { version = "0.151.1", features = ["serde-impl"] } +swc_common = "0.34.3" swc_error_reporters = "0.18.0" +swc_fast_ts_strip = "0.1.1" tracing = { version = "0.1.37", features = ["max_level_off"] } wasm-bindgen = { version = "0.2.82", features = ["enable-interning"] } wasm-bindgen-futures = { version = "0.4.41" } diff --git a/bindings/binding_typescript_wasm/__tests__/__snapshots__/transform.js.snap b/bindings/binding_typescript_wasm/__tests__/__snapshots__/transform.js.snap index 532010e65168..1b1e7769ce02 100644 --- a/bindings/binding_typescript_wasm/__tests__/__snapshots__/transform.js.snap +++ b/bindings/binding_typescript_wasm/__tests__/__snapshots__/transform.js.snap @@ -1,8 +1,66 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`transform in strip-only mode should throw an error when it encounters an enum 1`] = ` +exports[`transform in strip-only mode should remove declare enum 1`] = `""`; + +exports[`transform in strip-only mode should remove declare enum 2`] = `""`; + +exports[`transform in strip-only mode should remove declare enum 3`] = `""`; + +exports[`transform in strip-only mode should strip complex expressions 1`] = ` +"const foo = { + foo: 1, + bar: "bar", + }; + const bar = "bar";" +`; + +exports[`transform in strip-only mode should strip nonnull assertions 1`] = ` +"const foo = 1; + const bar = "bar";" +`; + +exports[`transform in strip-only mode should strip satisfies 1`] = ` +"const foo = 1; + const bar = "bar";" +`; + +exports[`transform in strip-only mode should strip type annotations 1`] = ` +"const foo = 1; + const bar = "bar";" +`; + +exports[`transform in strip-only mode should strip type assertions 1`] = ` +"const foo = 1; + const bar = "bar";" +`; + +exports[`transform in strip-only mode should strip type declarations 1`] = ` +"const foo = 1; + + + const bar = "bar";" +`; + +exports[`transform in strip-only mode should throw an error when it encounters a module 1`] = ` +" x TypeScript namespace declaration is not supported in strip-only mode + ,---- + 1 | module 'foo' {} + : ^^^^^^^^^^^^^^^ + \`---- " - x TypeScript enum is not supported in strip-only mode +`; + +exports[`transform in strip-only mode should throw an error when it encounters a namespace 1`] = ` +" x TypeScript namespace declaration is not supported in strip-only mode + ,---- + 1 | namespace Foo {} + : ^^^^^^^^^^^^^^^^ + \`---- +" +`; + +exports[`transform in strip-only mode should throw an error when it encounters an enum 1`] = ` +" x TypeScript enum is not supported in strip-only mode ,---- 1 | enum Foo {} : ^^^^^^^^^^^ @@ -11,8 +69,7 @@ exports[`transform in strip-only mode should throw an error when it encounters a `; exports[`transform in strip-only mode should throw an error with a descriptive message when it encounters a decorator 1`] = ` -" - x Decorators are not supported +" x Decorators are not supported ,---- 1 | class Foo { @decorator foo() {} } : ^^^^^^^^^^ @@ -20,13 +77,9 @@ exports[`transform in strip-only mode should throw an error with a descriptive m " `; -exports[`transform in transform mode should transpile enum 1`] = ` -"var Foo; -(function(Foo) {})(Foo || (Foo = {})); -" -`; - exports[`transform should strip types 1`] = ` -"export const foo = 1; " + export const foo = 1; + + " `; diff --git a/bindings/binding_typescript_wasm/__tests__/transform.js b/bindings/binding_typescript_wasm/__tests__/transform.js index 7cf8e6675ce8..4bacd9866381 100644 --- a/bindings/binding_typescript_wasm/__tests__/transform.js +++ b/bindings/binding_typescript_wasm/__tests__/transform.js @@ -8,7 +8,7 @@ it("properly reports error", function () { describe("transform", () => { it("should strip types", async () => { - const { code } = await swc.transform( + const code = await swc.transform( ` export const foo: number = 1; type Foo = number; @@ -19,6 +19,94 @@ describe("transform", () => { }); describe("in strip-only mode", () => { + it("should remove declare enum", async () => { + await expect( + swc.transform(`declare enum Foo {}`, {}) + ).resolves.toMatchSnapshot(); + await expect( + swc.transform( + `declare enum Foo { + A + }`, + {} + ) + ).resolves.toMatchSnapshot(); + expect( + swc.transform( + `declare enum Foo { + a = 2, + b, + }`, + {} + ) + ).resolves.toMatchSnapshot(); + }); + + it("should strip type declarations", async () => { + await expect( + swc.transform( + `const foo = 1; + type Foo = number; + type Bar = string; + const bar: Bar = "bar";`, + {} + ) + ).resolves.toMatchSnapshot(); + }); + + it("should strip type annotations", async () => { + await expect( + swc.transform( + `const foo = 1; + const bar: Bar = "bar";`, + {} + ) + ).resolves.toMatchSnapshot(); + }); + + it("should strip type assertions", async () => { + await expect( + swc.transform( + `const foo = 1 as number; + const bar = "bar";`, + {} + ) + ).resolves.toMatchSnapshot(); + }); + + it("should strip nonnull assertions", async () => { + await expect( + swc.transform( + `const foo = 1!; + const bar = "bar";`, + {} + ) + ).resolves.toMatchSnapshot(); + }); + + it("should strip satisfies", async () => { + await expect( + swc.transform( + `const foo = 1 satisfies number; + const bar = "bar";`, + {} + ) + ).resolves.toMatchSnapshot(); + }); + + it("should strip complex expressions", async () => { + await expect( + swc.transform( + `const foo = { + foo: 1 as number, + bar: "bar" as any as number, + } satisfies number; + const bar = "bar";`, + {} + ) + ).resolves.toMatchSnapshot(); + }); + it("should throw an error when it encounters an enum", async () => { await expect( swc.transform("enum Foo {}", { @@ -27,24 +115,28 @@ describe("transform", () => { ).rejects.toMatchSnapshot(); }); - it('should throw an error with a descriptive message when it encounters a decorator', async () => { + it("should throw an error with a descriptive message when it encounters a decorator", async () => { await expect( swc.transform("class Foo { @decorator foo() {} }", { mode: "strip-only", }) ).rejects.toMatchSnapshot(); - }) - }); - - describe("in transform mode", () => { - it("should transpile enum", async () => { - const { code } = await swc.transform("enum Foo {}", { - mode: "transform", - }); - - expect(code).toMatchSnapshot(); }); + it("should throw an error when it encounters a namespace", async () => { + await expect( + swc.transform("namespace Foo {}", { + mode: "strip-only", + }) + ).rejects.toMatchSnapshot(); + }); + it("should throw an error when it encounters a module", async () => { + await expect( + swc.transform("module 'foo' {}", { + mode: "strip-only", + }) + ).rejects.toMatchSnapshot(); + }); }); }); diff --git a/bindings/binding_typescript_wasm/src/lib.rs b/bindings/binding_typescript_wasm/src/lib.rs index e84f69d86fa2..7b4fc94d5b8c 100644 --- a/bindings/binding_typescript_wasm/src/lib.rs +++ b/bindings/binding_typescript_wasm/src/lib.rs @@ -1,32 +1,7 @@ -use anyhow::{Context, Error}; -use serde::{Deserialize, Serialize}; -use swc_core::{ - common::{ - comments::SingleThreadedComments, - errors::{ColorConfig, HANDLER}, - source_map::SourceMapGenConfig, - sync::Lrc, - FileName, Mark, SourceMap, Spanned, GLOBALS, - }, - ecma::{ - ast::{Decorator, EsVersion, Program, TsEnumDecl, TsParamPropParam}, - codegen::text_writer::JsWriter, - parser::{ - parse_file_as_module, parse_file_as_program, parse_file_as_script, Syntax, TsSyntax, - }, - transforms::{ - base::{ - fixer::fixer, - helpers::{inject_helpers, Helpers, HELPERS}, - hygiene::hygiene, - resolver, - }, - typescript::{strip_type, typescript}, - }, - visit::{Visit, VisitMutWith, VisitWith}, - }, -}; +use anyhow::Error; +use swc_common::{errors::ColorConfig, sync::Lrc, SourceMap, GLOBALS}; use swc_error_reporters::handler::{try_with_handler, HandlerOpts}; +use swc_fast_ts_strip::Options; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::{ future_to_promise, @@ -41,54 +16,6 @@ export function transform(src: string, opts?: Options): Promise export function transformSync(src: string, opts?: Options): TransformOutput; "#; -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Options { - #[serde(default)] - pub module: Option, - #[serde(default)] - pub filename: Option, - - #[serde(default = "default_ts_syntax")] - pub parser: TsSyntax, - - #[serde(default)] - pub external_helpers: bool, - - #[serde(default)] - pub source_maps: bool, - - #[serde(default)] - pub mode: Mode, - - #[serde(default)] - pub transform: Option, - - #[serde(default)] - pub codegen: swc_core::ecma::codegen::Config, -} - -fn default_ts_syntax() -> TsSyntax { - TsSyntax { - decorators: true, - ..Default::default() - } -} - -#[derive(Clone, Copy, Default, Deserialize)] -#[serde(rename_all = "kebab-case")] -pub enum Mode { - #[default] - StripOnly, - Transform, -} - -#[derive(Serialize)] -pub struct TransformOutput { - code: String, - map: Option, -} - #[wasm_bindgen] pub fn transform(input: JsString, options: JsValue) -> Promise { future_to_promise(async move { transform_sync(input, options) }) @@ -107,7 +34,7 @@ pub fn transform_sync(input: JsString, options: JsValue) -> Result Result { +fn operate(input: String, options: Options) -> Result { let cm = Lrc::new(SourceMap::default()); try_with_handler( @@ -116,177 +43,10 @@ fn operate(input: String, options: Options) -> Result { color: ColorConfig::Never, skip_filename: true, }, - |handler| { - let filename = options - .filename - .map_or(FileName::Anon, |f| FileName::Real(f.into())); - - let fm = cm.new_source_file(filename, input); - - let syntax = Syntax::Typescript(options.parser); - let target = EsVersion::latest(); - - let comments = SingleThreadedComments::default(); - let mut errors = vec![]; - - let program = match options.module { - Some(true) => { - parse_file_as_module(&fm, syntax, target, Some(&comments), &mut errors) - .map(Program::Module) - } - Some(false) => { - parse_file_as_script(&fm, syntax, target, Some(&comments), &mut errors) - .map(Program::Script) - } - None => parse_file_as_program(&fm, syntax, target, Some(&comments), &mut errors), - }; - - let mut program = match program { - Ok(program) => program, - Err(err) => { - err.into_diagnostic(handler).emit(); - - for e in errors { - e.into_diagnostic(handler).emit(); - } - - return Err(anyhow::anyhow!("failed to parse")); - } - }; - - if !errors.is_empty() { - for e in errors { - e.into_diagnostic(handler).emit(); - } - - return Err(anyhow::anyhow!("failed to parse")); - } - - let unresolved_mark = Mark::new(); - let top_level_mark = Mark::new(); - HELPERS.set(&Helpers::new(options.external_helpers), || { - // Apply resolver - - program.visit_mut_with(&mut resolver(unresolved_mark, top_level_mark, true)); - - // Strip typescript types - - program.visit_with(&mut Validator { mode: options.mode }); - - match options.mode { - Mode::StripOnly => { - program.visit_mut_with(&mut strip_type()); - } - Mode::Transform => { - program.visit_mut_with(&mut typescript( - options.transform.unwrap_or_default(), - top_level_mark, - )); - } - } - - // Apply external helpers - - program.visit_mut_with(&mut inject_helpers(unresolved_mark)); - - // Apply hygiene - - program.visit_mut_with(&mut hygiene()); - - // Apply fixer - - program.visit_mut_with(&mut fixer(Some(&comments))); - }); - - // Generate code - - let mut buf = vec![]; - let mut src_map_buf = if options.source_maps { - Some(vec![]) - } else { - None - }; - - { - let wr = JsWriter::new(cm.clone(), "\n", &mut buf, src_map_buf.as_mut()); - let mut emitter = swc_core::ecma::codegen::Emitter { - cfg: options.codegen, - cm: cm.clone(), - comments: Some(&comments), - wr, - }; - - emitter.emit_program(&program).unwrap(); - } - - let code = String::from_utf8(buf).context("generated code is not utf-8")?; - - let map = if let Some(src_map_buf) = src_map_buf { - let mut wr = vec![]; - let map = cm.build_source_map_with_config(&src_map_buf, None, TsSourceMapGenConfig); - - map.to_writer(&mut wr) - .context("failed to write source map")?; - - let map = String::from_utf8(wr).context("source map is not utf-8")?; - Some(map) - } else { - None - }; - - Ok(TransformOutput { code, map }) - }, + |handler| swc_fast_ts_strip::operate(&cm, handler, input, options), ) } pub fn convert_err(err: Error) -> wasm_bindgen::prelude::JsValue { format!("{:?}", err).into() } - -struct TsSourceMapGenConfig; - -impl SourceMapGenConfig for TsSourceMapGenConfig { - fn file_name_to_source(&self, f: &FileName) -> String { - f.to_string() - } -} - -struct Validator { - mode: Mode, -} - -impl Visit for Validator { - fn visit_decorator(&mut self, n: &Decorator) { - HANDLER.with(|handler| { - handler.span_err(n.span, "Decorators are not supported"); - }); - } - - fn visit_ts_enum_decl(&mut self, e: &TsEnumDecl) { - if matches!(self.mode, Mode::StripOnly) { - HANDLER.with(|handler| { - handler.span_err( - e.span, - "TypeScript enum is not supported in strip-only mode", - ); - }); - return; - } - - e.visit_children_with(self); - } - - fn visit_ts_param_prop_param(&mut self, n: &TsParamPropParam) { - if matches!(self.mode, Mode::StripOnly) { - HANDLER.with(|handler| { - handler.span_err( - n.span(), - "TypeScript parameter property is not supported in strip-only mode", - ); - }); - return; - } - - n.visit_children_with(self); - } -} diff --git a/crates/swc_ecma_transforms_proposal/tests/decorator-tests b/crates/swc_ecma_transforms_proposal/tests/decorator-tests index 8e9c0b0fb3d5..a03c69227413 160000 --- a/crates/swc_ecma_transforms_proposal/tests/decorator-tests +++ b/crates/swc_ecma_transforms_proposal/tests/decorator-tests @@ -1 +1 @@ -Subproject commit 8e9c0b0fb3d548f378420aabbd351087efb5d5e5 +Subproject commit a03c69227413dfcac8a1e9f89d93554fa3b8b7fe diff --git a/crates/swc_fast_ts_strip/Cargo.toml b/crates/swc_fast_ts_strip/Cargo.toml new file mode 100644 index 000000000000..96169197311b --- /dev/null +++ b/crates/swc_fast_ts_strip/Cargo.toml @@ -0,0 +1,23 @@ +[package] +authors = ["강동윤 "] +description = "Super-fast TypeScript stripper based on SWC" +documentation = "https://rustdoc.swc.rs/swc_fast_type_strip/" +edition = "2021" +include = ["Cargo.toml", "src/**/*.rs"] +license = "Apache-2.0" +name = "swc_fast_ts_strip" +repository = { workspace = true } +version = "0.1.1" + + +[dependencies] +anyhow = "1.0.66" +serde = { version = "1", features = ["derive"] } + +swc_common = { version = "0.34.3", path = "../swc_common" } +swc_ecma_ast = { version = "0.115.1", path = "../swc_ecma_ast" } +swc_ecma_parser = { version = "0.146.9", path = "../swc_ecma_parser" } +swc_ecma_visit = { version = "0.101.0", path = "../swc_ecma_visit" } + +[dev-dependencies] +testing = { version = "0.36.0", path = "../testing" } diff --git a/crates/swc_fast_ts_strip/src/lib.rs b/crates/swc_fast_ts_strip/src/lib.rs new file mode 100644 index 000000000000..5a0c4ef740bf --- /dev/null +++ b/crates/swc_fast_ts_strip/src/lib.rs @@ -0,0 +1,245 @@ +use anyhow::Error; +use serde::Deserialize; +use swc_common::{ + comments::SingleThreadedComments, + errors::{Handler, HANDLER}, + sync::Lrc, + BytePos, FileName, SourceMap, Span, Spanned, +}; +use swc_ecma_ast::{ + BindingIdent, Decorator, EsVersion, Ident, Param, Pat, Program, TsAsExpr, TsConstAssertion, + TsEnumDecl, TsInstantiation, TsModuleDecl, TsNamespaceDecl, TsNonNullExpr, TsParamPropParam, + TsSatisfiesExpr, TsTypeAliasDecl, TsTypeAnn, +}; +use swc_ecma_parser::{ + parse_file_as_module, parse_file_as_program, parse_file_as_script, Syntax, TsSyntax, +}; +use swc_ecma_visit::{Visit, VisitWith}; + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Options { + #[serde(default)] + pub module: Option, + #[serde(default)] + pub filename: Option, + + #[serde(default = "default_ts_syntax")] + pub parser: TsSyntax, +} + +fn default_ts_syntax() -> TsSyntax { + TsSyntax { + decorators: true, + ..Default::default() + } +} + +pub fn operate( + cm: &Lrc, + handler: &Handler, + input: String, + options: Options, +) -> Result { + let filename = options + .filename + .map_or(FileName::Anon, |f| FileName::Real(f.into())); + + let fm = cm.new_source_file(filename, input); + + let syntax = Syntax::Typescript(options.parser); + let target = EsVersion::latest(); + + let comments = SingleThreadedComments::default(); + let mut errors = vec![]; + + let program = match options.module { + Some(true) => parse_file_as_module(&fm, syntax, target, Some(&comments), &mut errors) + .map(Program::Module), + Some(false) => parse_file_as_script(&fm, syntax, target, Some(&comments), &mut errors) + .map(Program::Script), + None => parse_file_as_program(&fm, syntax, target, Some(&comments), &mut errors), + }; + + let program = match program { + Ok(program) => program, + Err(err) => { + err.into_diagnostic(handler).emit(); + + for e in errors { + e.into_diagnostic(handler).emit(); + } + + return Err(anyhow::anyhow!("failed to parse")); + } + }; + + if !errors.is_empty() { + for e in errors { + e.into_diagnostic(handler).emit(); + } + + return Err(anyhow::anyhow!("failed to parse")); + } + + // Strip typescript types + let mut ts_strip = TsStrip::default(); + program.visit_with(&mut ts_strip); + + let replacements = ts_strip.replacements; + + if replacements.is_empty() { + return Ok(fm.src.to_string()); + } + + let mut code = ::clone(&fm.src).into_bytes(); + + for r in replacements { + code[(r.0 .0 - 1) as usize..(r.1 .0 - 1) as usize] + .iter_mut() + .for_each(|b| *b = b' '); + } + + String::from_utf8(code).map_err(|_| anyhow::anyhow!("failed to convert to utf-8")) +} + +#[derive(Default)] +struct TsStrip { + replacements: Vec<(BytePos, BytePos)>, +} + +impl TsStrip { + fn add_replacement(&mut self, span: Span) { + self.replacements.push((span.lo, span.hi)); + } +} + +impl Visit for TsStrip { + fn visit_decorator(&mut self, n: &Decorator) { + HANDLER.with(|handler| { + handler.span_err(n.span, "Decorators are not supported"); + }); + } + + fn visit_ts_as_expr(&mut self, n: &TsAsExpr) { + self.add_replacement(span(n.expr.span().hi, n.span.hi)); + + n.expr.visit_children_with(self); + } + + fn visit_ts_const_assertion(&mut self, n: &TsConstAssertion) { + self.add_replacement(span(n.expr.span().hi, n.span.hi)); + + n.expr.visit_children_with(self); + } + + fn visit_ts_enum_decl(&mut self, e: &TsEnumDecl) { + if e.declare { + self.add_replacement(e.span); + return; + } + + HANDLER.with(|handler| { + handler.span_err( + e.span, + "TypeScript enum is not supported in strip-only mode", + ); + }); + } + + fn visit_ts_instantiation(&mut self, n: &TsInstantiation) { + self.add_replacement(span(n.expr.span().hi, n.span.hi)); + + n.expr.visit_children_with(self); + } + + fn visit_ts_module_decl(&mut self, n: &TsModuleDecl) { + if n.declare { + self.add_replacement(n.span); + return; + } + + HANDLER.with(|handler| { + handler.span_err( + n.span(), + "TypeScript namespace declaration is not supported in strip-only mode", + ); + }); + } + + fn visit_ts_namespace_decl(&mut self, n: &TsNamespaceDecl) { + if n.declare { + self.add_replacement(n.span); + return; + } + + HANDLER.with(|handler| { + handler.span_err( + n.span(), + "TypeScript module declaration is not supported in strip-only mode", + ); + }); + } + + fn visit_ts_non_null_expr(&mut self, n: &TsNonNullExpr) { + self.add_replacement(span(n.span.hi - BytePos(1), n.span.hi)); + + n.expr.visit_children_with(self); + } + + fn visit_ts_param_prop_param(&mut self, n: &TsParamPropParam) { + HANDLER.with(|handler| { + handler.span_err( + n.span(), + "TypeScript parameter property is not supported in strip-only mode", + ); + }); + } + + fn visit_ts_satisfies_expr(&mut self, n: &TsSatisfiesExpr) { + self.add_replacement(span(n.expr.span().hi, n.span.hi)); + + n.expr.visit_children_with(self); + } + + fn visit_ts_type_alias_decl(&mut self, n: &TsTypeAliasDecl) { + self.add_replacement(n.span); + } + + fn visit_ts_type_ann(&mut self, n: &TsTypeAnn) { + self.add_replacement(n.span); + } + + fn visit_binding_ident(&mut self, n: &BindingIdent) { + n.visit_children_with(self); + + if n.optional { + self.add_replacement(span(n.id.span.hi, n.id.span.hi + BytePos(1))); + } + } + + fn visit_params(&mut self, n: &[Param]) { + if let Some(p) = n.first().filter(|param| { + matches!( + ¶m.pat, + Pat::Ident(BindingIdent { + id: Ident { sym, .. }, + .. + }) if &**sym == "this" + ) + }) { + let lo = p.span.lo; + let hi = n.get(1).map(|x| x.span.lo).unwrap_or(p.span.hi); + self.add_replacement(span(lo, hi)); + + n[1..].visit_children_with(self); + return; + } + + n.visit_children_with(self); + } +} + +fn span(lo: BytePos, hi: BytePos) -> Span { + Span::new(lo, hi, Default::default()) +} diff --git a/crates/swc_fast_ts_strip/tests/errors/decorators.swc-stderr b/crates/swc_fast_ts_strip/tests/errors/decorators.swc-stderr new file mode 100644 index 000000000000..a707ae53c04e --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/errors/decorators.swc-stderr @@ -0,0 +1,5 @@ + x Decorators are not supported + ,---- + 1 | class Foo { @decorator foo() { } } + : ^^^^^^^^^^ + `---- diff --git a/crates/swc_fast_ts_strip/tests/errors/decorators.ts b/crates/swc_fast_ts_strip/tests/errors/decorators.ts new file mode 100644 index 000000000000..dc17a54c03f7 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/errors/decorators.ts @@ -0,0 +1 @@ +class Foo { @decorator foo() { } } \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/errors/enums.swc-stderr b/crates/swc_fast_ts_strip/tests/errors/enums.swc-stderr new file mode 100644 index 000000000000..2efbeccbfe87 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/errors/enums.swc-stderr @@ -0,0 +1,5 @@ + x TypeScript enum is not supported in strip-only mode + ,---- + 1 | enum Foo { } + : ^^^^^^^^^^^^ + `---- diff --git a/crates/swc_fast_ts_strip/tests/errors/enums.ts b/crates/swc_fast_ts_strip/tests/errors/enums.ts new file mode 100644 index 000000000000..dfa841058431 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/errors/enums.ts @@ -0,0 +1 @@ +enum Foo { } \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/errors/modules.swc-stderr b/crates/swc_fast_ts_strip/tests/errors/modules.swc-stderr new file mode 100644 index 000000000000..6f2fc101fe8a --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/errors/modules.swc-stderr @@ -0,0 +1,5 @@ + x TypeScript namespace declaration is not supported in strip-only mode + ,---- + 1 | module 'foo' { } + : ^^^^^^^^^^^^^^^^ + `---- diff --git a/crates/swc_fast_ts_strip/tests/errors/modules.ts b/crates/swc_fast_ts_strip/tests/errors/modules.ts new file mode 100644 index 000000000000..0a6968cccaae --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/errors/modules.ts @@ -0,0 +1 @@ +module 'foo' { } \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/errors/namespaces.swc-stderr b/crates/swc_fast_ts_strip/tests/errors/namespaces.swc-stderr new file mode 100644 index 000000000000..ae5fe90b0de2 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/errors/namespaces.swc-stderr @@ -0,0 +1,5 @@ + x TypeScript namespace declaration is not supported in strip-only mode + ,---- + 1 | namespace Foo { } + : ^^^^^^^^^^^^^^^^^ + `---- diff --git a/crates/swc_fast_ts_strip/tests/errors/namespaces.ts b/crates/swc_fast_ts_strip/tests/errors/namespaces.ts new file mode 100644 index 000000000000..f10df856e654 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/errors/namespaces.ts @@ -0,0 +1 @@ +namespace Foo { } \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture.rs b/crates/swc_fast_ts_strip/tests/fixture.rs new file mode 100644 index 000000000000..9d5db3e5c8c9 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture.rs @@ -0,0 +1,48 @@ +use std::path::PathBuf; + +use swc_ecma_parser::TsSyntax; +use swc_fast_ts_strip::{operate, Options}; +use testing::NormalizedOutput; + +#[testing::fixture("tests/fixture/**/*.ts")] +fn test(input: PathBuf) { + let input_code = std::fs::read_to_string(&input).unwrap(); + let output_file = input.with_extension("js"); + + testing::run_test(false, |cm, handler| { + let code = operate(&cm, handler, input_code, opts()).expect("should not return Err()"); + + NormalizedOutput::new_raw(code) + .compare_to_file(output_file) + .unwrap(); + + Ok(()) + }) + .expect("should not fail"); +} + +#[testing::fixture("tests/errors/**/*.ts")] +fn error(input: PathBuf) { + let input_code = std::fs::read_to_string(&input).unwrap(); + let output_file = input.with_extension("swc-stderr"); + + testing::run_test(false, |cm, handler| { + operate(&cm, handler, input_code, opts()).expect("should not return Err()"); + + Err::<(), _>(()) + }) + .expect_err("should fail") + .compare_to_file(output_file) + .unwrap(); +} + +fn opts() -> Options { + Options { + module: None, + filename: None, + parser: TsSyntax { + decorators: true, + ..Default::default() + }, + } +} diff --git a/crates/swc_fast_ts_strip/tests/fixture/const-assertion.js b/crates/swc_fast_ts_strip/tests/fixture/const-assertion.js new file mode 100644 index 000000000000..63c8f7b27ab8 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/const-assertion.js @@ -0,0 +1,3 @@ + + +const foo = [1, 3, 5] ; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/const-assertion.ts b/crates/swc_fast_ts_strip/tests/fixture/const-assertion.ts new file mode 100644 index 000000000000..f822a162c96b --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/const-assertion.ts @@ -0,0 +1,3 @@ + + +const foo = [1, 3, 5] as const; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/declare-enum/empty.js b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/empty.js new file mode 100644 index 000000000000..4eea3e2ad7d8 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/empty.js @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/declare-enum/empty.ts b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/empty.ts new file mode 100644 index 000000000000..6fdcedadd26b --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/empty.ts @@ -0,0 +1 @@ +declare enum Foo { } \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/declare-enum/simple.js b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/simple.js new file mode 100644 index 000000000000..ad80c5a8877a --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/simple.js @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/declare-enum/simple.ts b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/simple.ts new file mode 100644 index 000000000000..e66d4f1ed41e --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/simple.ts @@ -0,0 +1,3 @@ +declare enum Foo { + A +} \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/declare-enum/with-init.js b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/with-init.js new file mode 100644 index 000000000000..bc2ddb2b6b4b --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/with-init.js @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/declare-enum/with-init.ts b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/with-init.ts new file mode 100644 index 000000000000..8d2ebaa1b7c1 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/declare-enum/with-init.ts @@ -0,0 +1,4 @@ +declare enum Foo { + a = 2, + b, +} \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/instantiation-expr.js b/crates/swc_fast_ts_strip/tests/fixture/instantiation-expr.js new file mode 100644 index 000000000000..83b298de7a67 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/instantiation-expr.js @@ -0,0 +1,3 @@ + + +const foo = call \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/instantiation-expr.ts b/crates/swc_fast_ts_strip/tests/fixture/instantiation-expr.ts new file mode 100644 index 000000000000..0fcee5f0ae27 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/instantiation-expr.ts @@ -0,0 +1,3 @@ + + +const foo = call \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/mixed/1.js b/crates/swc_fast_ts_strip/tests/fixture/mixed/1.js new file mode 100644 index 000000000000..9ce8b5bfcf9c --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/mixed/1.js @@ -0,0 +1,6 @@ +const foo = { + foo: 1 , + bar: "bar" , + baz: foo , +} ; +const bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/mixed/1.ts b/crates/swc_fast_ts_strip/tests/fixture/mixed/1.ts new file mode 100644 index 000000000000..39c86126d648 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/mixed/1.ts @@ -0,0 +1,6 @@ +const foo = { + foo: 1 as number, + bar: "bar" as any as number, + baz: foo as const, +} satisfies number; +const bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/nonnull-assertion/1.js b/crates/swc_fast_ts_strip/tests/fixture/nonnull-assertion/1.js new file mode 100644 index 000000000000..11b0967b9087 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/nonnull-assertion/1.js @@ -0,0 +1,2 @@ +const foo = 1 ; +const bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/nonnull-assertion/1.ts b/crates/swc_fast_ts_strip/tests/fixture/nonnull-assertion/1.ts new file mode 100644 index 000000000000..760cee8a37d0 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/nonnull-assertion/1.ts @@ -0,0 +1,2 @@ +const foo = 1!; +const bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/pat-optional.js b/crates/swc_fast_ts_strip/tests/fixture/pat-optional.js new file mode 100644 index 000000000000..567ea005ce14 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/pat-optional.js @@ -0,0 +1,9 @@ + + +export function typeAnn({ a, b, c } ) { + console.log(a, b, c); +} + +export function optional(a ) { + console.log(a, b, c); +} \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/pat-optional.ts b/crates/swc_fast_ts_strip/tests/fixture/pat-optional.ts new file mode 100644 index 000000000000..a1a17722138e --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/pat-optional.ts @@ -0,0 +1,9 @@ + + +export function typeAnn({ a, b, c }: { a: number; b: number; c?: number }) { + console.log(a, b, c); +} + +export function optional(a?: string) { + console.log(a, b, c); +} \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/satisfies/1.js b/crates/swc_fast_ts_strip/tests/fixture/satisfies/1.js new file mode 100644 index 000000000000..514d80a4b130 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/satisfies/1.js @@ -0,0 +1,2 @@ +const foo = 1 ; +const bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/satisfies/1.ts b/crates/swc_fast_ts_strip/tests/fixture/satisfies/1.ts new file mode 100644 index 000000000000..c44f9df69e18 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/satisfies/1.ts @@ -0,0 +1,2 @@ +const foo = 1 satisfies number; +const bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/this-param.js b/crates/swc_fast_ts_strip/tests/fixture/this-param.js new file mode 100644 index 000000000000..fc1c9fa0db1e --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/this-param.js @@ -0,0 +1,2 @@ +export function foo( ) {} +export function bar( x ) {} \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/this-param.ts b/crates/swc_fast_ts_strip/tests/fixture/this-param.ts new file mode 100644 index 000000000000..8d8653d61c5b --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/this-param.ts @@ -0,0 +1,2 @@ +export function foo(this: number): void {} +export function bar(this: number, x: string): void {} \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/type-alias/1.js b/crates/swc_fast_ts_strip/tests/fixture/type-alias/1.js new file mode 100644 index 000000000000..3baea597ea05 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/type-alias/1.js @@ -0,0 +1,2 @@ +export const foo = 1; + \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/type-alias/1.ts b/crates/swc_fast_ts_strip/tests/fixture/type-alias/1.ts new file mode 100644 index 000000000000..985934fc30e4 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/type-alias/1.ts @@ -0,0 +1,2 @@ +export const foo: number = 1; +type Foo = number; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/type-alias/2.js b/crates/swc_fast_ts_strip/tests/fixture/type-alias/2.js new file mode 100644 index 000000000000..d53287b92ba4 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/type-alias/2.js @@ -0,0 +1,4 @@ +const foo = 1; + + +const bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/type-alias/2.ts b/crates/swc_fast_ts_strip/tests/fixture/type-alias/2.ts new file mode 100644 index 000000000000..516963863300 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/type-alias/2.ts @@ -0,0 +1,4 @@ +const foo = 1; +type Foo = number; +type Bar = string; +const bar: Bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/type-ann/var-decl/1.js b/crates/swc_fast_ts_strip/tests/fixture/type-ann/var-decl/1.js new file mode 100644 index 000000000000..22c4cf57ce1e --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/type-ann/var-decl/1.js @@ -0,0 +1,2 @@ +const foo = 1; +const bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/type-ann/var-decl/1.ts b/crates/swc_fast_ts_strip/tests/fixture/type-ann/var-decl/1.ts new file mode 100644 index 000000000000..d2d1ceb9c074 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/type-ann/var-decl/1.ts @@ -0,0 +1,2 @@ +const foo = 1; +const bar: Bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/type-assertions/1.js b/crates/swc_fast_ts_strip/tests/fixture/type-assertions/1.js new file mode 100644 index 000000000000..924e1f856193 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/type-assertions/1.js @@ -0,0 +1,2 @@ +const foo = 1 ; +const bar = "bar"; \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/type-assertions/1.ts b/crates/swc_fast_ts_strip/tests/fixture/type-assertions/1.ts new file mode 100644 index 000000000000..f6b9c0a993da --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/type-assertions/1.ts @@ -0,0 +1,2 @@ +const foo = 1 as number; +const bar = "bar"; \ No newline at end of file