Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(bindings/ts): Add transform/strip-only mode #9138

Merged
merged 7 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions bindings/binding_typescript_wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ bench = false
crate-type = ["cdylib"]

[features]
default = ["swc_v1"]
swc_v1 = []
swc_v2 = []

[dependencies]
anyhow = "1.0.66"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

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 {}
: ^^^^^^^^^^^
\`----
"
`;

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;
"
`;
42 changes: 22 additions & 20 deletions bindings/binding_typescript_wasm/__tests__/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ it("properly reports error", function () {
}).toThrow();
});

describe("trannsform", () => {
describe("transform", () => {
it("should strip types", async () => {
const { code } = await swc.transform(
`
Expand All @@ -15,26 +15,28 @@ describe("trannsform", () => {
`,
{}
);
expect(code).toMatchInlineSnapshot(`
"export const foo = 1;
"
`);
expect(code).toMatchSnapshot();
});

it("should preserve enum", async () => {
const { code } = await swc.transform(
`
enum Foo {
Bar
}
`,
{}
);
await expect(code).toMatchInlineSnapshot(`
"enum Foo {
Bar
}
"
`);
describe("in strip-only mode", () => {
it("should throw an error when it encounters an enum", async () => {
await expect(
swc.transform("enum 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();
});


});
});
2 changes: 1 addition & 1 deletion bindings/binding_typescript_wasm/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"devDependencies": {
"jest": "^25.1.0"
"jest": "^29.7.0"
}
}
66 changes: 57 additions & 9 deletions bindings/binding_typescript_wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ use anyhow::{Context, Error};
use serde::{Deserialize, Serialize};
use swc_core::{
common::{
comments::SingleThreadedComments, errors::ColorConfig, source_map::SourceMapGenConfig,
sync::Lrc, FileName, Mark, SourceMap, GLOBALS,
comments::SingleThreadedComments,
errors::{ColorConfig, HANDLER},
source_map::SourceMapGenConfig,
sync::Lrc,
FileName, Mark, SourceMap, Spanned, GLOBALS,
},
ecma::{
ast::{EsVersion, Program},
ast::{EsVersion, Program, TsEnumDecl, TsParamPropParam},
codegen::text_writer::JsWriter,
parser::{
parse_file_as_module, parse_file_as_program, parse_file_as_script, Syntax, TsSyntax,
Expand All @@ -18,9 +21,9 @@ use swc_core::{
hygiene::hygiene,
resolver,
},
typescript::strip_type,
typescript::{strip_type, typescript},
},
visit::VisitMutWith,
visit::{Visit, VisitMutWith, VisitWith},
},
};
use swc_error_reporters::handler::{try_with_handler, HandlerOpts};
Expand Down Expand Up @@ -55,12 +58,24 @@ pub struct Options {
#[serde(default)]
pub source_maps: bool,

// #[serde(default)]
// pub transform: swc_core::ecma::transforms::typescript::Config,
#[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,
}

#[derive(Default, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum Mode {
#[default]
StripOnly,
Transform,
}

#[derive(Serialize)]
pub struct TransformOutput {
code: String,
Expand Down Expand Up @@ -142,15 +157,26 @@ fn operate(input: String, options: Options) -> Result<TransformOutput, Error> {

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_mut_with(&mut strip_type());
match options.mode {
Mode::StripOnly => {
program.visit_with(&mut ThrowOnCodegen);

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

Expand Down Expand Up @@ -217,3 +243,25 @@ impl SourceMapGenConfig for TsSourceMapGenConfig {
f.to_string()
}
}

struct ThrowOnCodegen;

impl Visit for ThrowOnCodegen {
fn visit_ts_enum_decl(&mut self, e: &TsEnumDecl) {
HANDLER.with(|handler| {
handler.span_err(
e.span,
"TypeScript enum is not supported in strip-only mode",
);
});
}

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",
);
});
}
}
Loading