mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 00:32:15 +03:00
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 <akari.ccino@gmail.com>
This commit is contained in:
parent
ce78baa17d
commit
b129343c94
12
.github/workflows/CI.yml
vendored
12
.github/workflows/CI.yml
vendored
@ -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
|
||||
|
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -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"
|
||||
|
@ -24,6 +24,7 @@ members = [
|
||||
"crates/swc_x_optimizer",
|
||||
"crates/swc_transform_common",
|
||||
"crates/swc_typescript",
|
||||
"crates/swc_fast_ts_strip",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
|
118
bindings/Cargo.lock
generated
118
bindings/Cargo.lock
generated
@ -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"
|
||||
|
@ -0,0 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`minify should work 1`] = `
|
||||
Object {
|
||||
"code": "console.log(1);",
|
||||
}
|
||||
`;
|
15
bindings/binding_minifier_wasm/__tests__/simple.js
Normal file
15
bindings/binding_minifier_wasm/__tests__/simple.js
Normal file
@ -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();
|
||||
});
|
||||
});
|
6
bindings/binding_minifier_wasm/scripts/test.sh
Executable file
6
bindings/binding_minifier_wasm/scripts/test.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
wasm-pack build --out-name wasm --release --scope=swc --target nodejs
|
||||
npx jest $@
|
@ -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" }
|
||||
|
@ -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;
|
||||
|
||||
"
|
||||
`;
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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<TransformOutput>
|
||||
export function transformSync(src: string, opts?: Options): TransformOutput;
|
||||
"#;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Options {
|
||||
#[serde(default)]
|
||||
pub module: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub filename: Option<String>,
|
||||
|
||||
#[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<swc_core::ecma::transforms::typescript::Config>,
|
||||
|
||||
#[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<String>,
|
||||
}
|
||||
|
||||
#[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<JsValue, JsVa
|
||||
Ok(serde_wasm_bindgen::to_value(&result)?)
|
||||
}
|
||||
|
||||
fn operate(input: String, options: Options) -> Result<TransformOutput, Error> {
|
||||
fn operate(input: String, options: Options) -> Result<String, Error> {
|
||||
let cm = Lrc::new(SourceMap::default());
|
||||
|
||||
try_with_handler(
|
||||
@ -116,177 +43,10 @@ fn operate(input: String, options: Options) -> Result<TransformOutput, Error> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 8e9c0b0fb3d548f378420aabbd351087efb5d5e5
|
||||
Subproject commit a03c69227413dfcac8a1e9f89d93554fa3b8b7fe
|
23
crates/swc_fast_ts_strip/Cargo.toml
Normal file
23
crates/swc_fast_ts_strip/Cargo.toml
Normal file
@ -0,0 +1,23 @@
|
||||
[package]
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
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" }
|
245
crates/swc_fast_ts_strip/src/lib.rs
Normal file
245
crates/swc_fast_ts_strip/src/lib.rs
Normal file
@ -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<bool>,
|
||||
#[serde(default)]
|
||||
pub filename: Option<String>,
|
||||
|
||||
#[serde(default = "default_ts_syntax")]
|
||||
pub parser: TsSyntax,
|
||||
}
|
||||
|
||||
fn default_ts_syntax() -> TsSyntax {
|
||||
TsSyntax {
|
||||
decorators: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn operate(
|
||||
cm: &Lrc<SourceMap>,
|
||||
handler: &Handler,
|
||||
input: String,
|
||||
options: Options,
|
||||
) -> Result<String, Error> {
|
||||
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 = <std::string::String as Clone>::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())
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
x Decorators are not supported
|
||||
,----
|
||||
1 | class Foo { @decorator foo() { } }
|
||||
: ^^^^^^^^^^
|
||||
`----
|
1
crates/swc_fast_ts_strip/tests/errors/decorators.ts
Normal file
1
crates/swc_fast_ts_strip/tests/errors/decorators.ts
Normal file
@ -0,0 +1 @@
|
||||
class Foo { @decorator foo() { } }
|
5
crates/swc_fast_ts_strip/tests/errors/enums.swc-stderr
Normal file
5
crates/swc_fast_ts_strip/tests/errors/enums.swc-stderr
Normal file
@ -0,0 +1,5 @@
|
||||
x TypeScript enum is not supported in strip-only mode
|
||||
,----
|
||||
1 | enum Foo { }
|
||||
: ^^^^^^^^^^^^
|
||||
`----
|
1
crates/swc_fast_ts_strip/tests/errors/enums.ts
Normal file
1
crates/swc_fast_ts_strip/tests/errors/enums.ts
Normal file
@ -0,0 +1 @@
|
||||
enum Foo { }
|
5
crates/swc_fast_ts_strip/tests/errors/modules.swc-stderr
Normal file
5
crates/swc_fast_ts_strip/tests/errors/modules.swc-stderr
Normal file
@ -0,0 +1,5 @@
|
||||
x TypeScript namespace declaration is not supported in strip-only mode
|
||||
,----
|
||||
1 | module 'foo' { }
|
||||
: ^^^^^^^^^^^^^^^^
|
||||
`----
|
1
crates/swc_fast_ts_strip/tests/errors/modules.ts
Normal file
1
crates/swc_fast_ts_strip/tests/errors/modules.ts
Normal file
@ -0,0 +1 @@
|
||||
module 'foo' { }
|
@ -0,0 +1,5 @@
|
||||
x TypeScript namespace declaration is not supported in strip-only mode
|
||||
,----
|
||||
1 | namespace Foo { }
|
||||
: ^^^^^^^^^^^^^^^^^
|
||||
`----
|
1
crates/swc_fast_ts_strip/tests/errors/namespaces.ts
Normal file
1
crates/swc_fast_ts_strip/tests/errors/namespaces.ts
Normal file
@ -0,0 +1 @@
|
||||
namespace Foo { }
|
48
crates/swc_fast_ts_strip/tests/fixture.rs
Normal file
48
crates/swc_fast_ts_strip/tests/fixture.rs
Normal file
@ -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()
|
||||
},
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
const foo = [1, 3, 5] ;
|
@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
const foo = [1, 3, 5] as const;
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1 @@
|
||||
declare enum Foo { }
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1,3 @@
|
||||
declare enum Foo {
|
||||
A
|
||||
}
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1,4 @@
|
||||
declare enum Foo {
|
||||
a = 2,
|
||||
b,
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
const foo = call
|
@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
const foo = call<string>
|
6
crates/swc_fast_ts_strip/tests/fixture/mixed/1.js
Normal file
6
crates/swc_fast_ts_strip/tests/fixture/mixed/1.js
Normal file
@ -0,0 +1,6 @@
|
||||
const foo = {
|
||||
foo: 1 ,
|
||||
bar: "bar" ,
|
||||
baz: foo ,
|
||||
} ;
|
||||
const bar = "bar";
|
6
crates/swc_fast_ts_strip/tests/fixture/mixed/1.ts
Normal file
6
crates/swc_fast_ts_strip/tests/fixture/mixed/1.ts
Normal file
@ -0,0 +1,6 @@
|
||||
const foo = {
|
||||
foo: 1 as number,
|
||||
bar: "bar" as any as number,
|
||||
baz: foo<string> as const,
|
||||
} satisfies number;
|
||||
const bar = "bar";
|
@ -0,0 +1,2 @@
|
||||
const foo = 1 ;
|
||||
const bar = "bar";
|
@ -0,0 +1,2 @@
|
||||
const foo = 1!;
|
||||
const bar = "bar";
|
9
crates/swc_fast_ts_strip/tests/fixture/pat-optional.js
Normal file
9
crates/swc_fast_ts_strip/tests/fixture/pat-optional.js
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
export function typeAnn({ a, b, c } ) {
|
||||
console.log(a, b, c);
|
||||
}
|
||||
|
||||
export function optional(a ) {
|
||||
console.log(a, b, c);
|
||||
}
|
9
crates/swc_fast_ts_strip/tests/fixture/pat-optional.ts
Normal file
9
crates/swc_fast_ts_strip/tests/fixture/pat-optional.ts
Normal file
@ -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);
|
||||
}
|
2
crates/swc_fast_ts_strip/tests/fixture/satisfies/1.js
Normal file
2
crates/swc_fast_ts_strip/tests/fixture/satisfies/1.js
Normal file
@ -0,0 +1,2 @@
|
||||
const foo = 1 ;
|
||||
const bar = "bar";
|
2
crates/swc_fast_ts_strip/tests/fixture/satisfies/1.ts
Normal file
2
crates/swc_fast_ts_strip/tests/fixture/satisfies/1.ts
Normal file
@ -0,0 +1,2 @@
|
||||
const foo = 1 satisfies number;
|
||||
const bar = "bar";
|
2
crates/swc_fast_ts_strip/tests/fixture/this-param.js
Normal file
2
crates/swc_fast_ts_strip/tests/fixture/this-param.js
Normal file
@ -0,0 +1,2 @@
|
||||
export function foo( ) {}
|
||||
export function bar( x ) {}
|
2
crates/swc_fast_ts_strip/tests/fixture/this-param.ts
Normal file
2
crates/swc_fast_ts_strip/tests/fixture/this-param.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export function foo(this: number): void {}
|
||||
export function bar(this: number, x: string): void {}
|
2
crates/swc_fast_ts_strip/tests/fixture/type-alias/1.js
Normal file
2
crates/swc_fast_ts_strip/tests/fixture/type-alias/1.js
Normal file
@ -0,0 +1,2 @@
|
||||
export const foo = 1;
|
||||
|
2
crates/swc_fast_ts_strip/tests/fixture/type-alias/1.ts
Normal file
2
crates/swc_fast_ts_strip/tests/fixture/type-alias/1.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const foo: number = 1;
|
||||
type Foo = number;
|
4
crates/swc_fast_ts_strip/tests/fixture/type-alias/2.js
Normal file
4
crates/swc_fast_ts_strip/tests/fixture/type-alias/2.js
Normal file
@ -0,0 +1,4 @@
|
||||
const foo = 1;
|
||||
|
||||
|
||||
const bar = "bar";
|
4
crates/swc_fast_ts_strip/tests/fixture/type-alias/2.ts
Normal file
4
crates/swc_fast_ts_strip/tests/fixture/type-alias/2.ts
Normal file
@ -0,0 +1,4 @@
|
||||
const foo = 1;
|
||||
type Foo = number;
|
||||
type Bar = string;
|
||||
const bar: Bar = "bar";
|
@ -0,0 +1,2 @@
|
||||
const foo = 1;
|
||||
const bar = "bar";
|
@ -0,0 +1,2 @@
|
||||
const foo = 1;
|
||||
const bar: Bar = "bar";
|
@ -0,0 +1,2 @@
|
||||
const foo = 1 ;
|
||||
const bar = "bar";
|
@ -0,0 +1,2 @@
|
||||
const foo = 1 as number;
|
||||
const bar = "bar";
|
Loading…
Reference in New Issue
Block a user