Skip to content

Commit b82f905

Browse files
committed
Add lossless ast tests
1 parent a9812ce commit b82f905

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/swc_plugin_backend_tests/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@ publish = false
1212
bench = false
1313
doctest = false
1414

15+
[features]
16+
# for ast_node macro
17+
default = ["encoding-impl"]
18+
__rkyv = []
19+
rkyv-impl = []
20+
serde-impl = []
21+
encoding-impl = []
22+
23+
[lints.rust]
24+
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(swc_ast_unknown)'] }
25+
1526
[dev-dependencies]
1627
anyhow = { workspace = true }
1728
codspeed-criterion-compat = { workspace = true }
@@ -20,6 +31,7 @@ serde = { workspace = true, features = ["derive"] }
2031
serde_json = { workspace = true }
2132
tokio = { workspace = true, features = ["rt"] }
2233
tracing = { workspace = true }
34+
cbor4ii = { workspace = true, features = [ "use_std" ] }
2335

2436
swc_common = { version = "16.0.0", path = "../swc_common", features = [
2537
"concurrent",
@@ -40,3 +52,9 @@ swc_plugin_backend_wasmtime = { version = "3.0", path = "../swc_plugin_backend_w
4052
[[bench]]
4153
harness = false
4254
name = "ecma_invoke"
55+
56+
[package.metadata.cargo-shear]
57+
ignored = [
58+
# false positive, use by ast_node macro
59+
"cbor4ii",
60+
]
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
use std::{
2+
env, fs,
3+
path::{Path, PathBuf},
4+
process::{Command, Stdio},
5+
sync::Arc,
6+
};
7+
8+
use anyhow::{anyhow, Error};
9+
use serde_json::json;
10+
use swc_common::{
11+
ast_node,
12+
plugin::{metadata::TransformPluginMetadataContext, serialized::PluginSerializedBytes},
13+
sync::Lazy,
14+
BytePos, EqIgnoreSpan, FileName, Mark, Span,
15+
};
16+
use swc_ecma_ast::{Module, Script};
17+
use swc_plugin_runner::{plugin_module_bytes::CompiledPluginModuleBytes, runtime::Runtime};
18+
use testing::CARGO_TARGET_DIR;
19+
20+
/// Returns the path to the built plugin
21+
fn build_plugin(dir: &Path) -> Result<PathBuf, Error> {
22+
{
23+
let mut cmd = Command::new("cargo");
24+
cmd.env("CARGO_TARGET_DIR", &*CARGO_TARGET_DIR);
25+
cmd.current_dir(dir);
26+
cmd.args(["build", "--target=wasm32-wasip1"])
27+
.stderr(Stdio::inherit());
28+
cmd.output()?;
29+
30+
if !cmd
31+
.status()
32+
.expect("Exit code should be available")
33+
.success()
34+
{
35+
return Err(anyhow!("Failed to build plugin"));
36+
}
37+
}
38+
39+
for entry in fs::read_dir(CARGO_TARGET_DIR.join("wasm32-wasip1").join("debug"))? {
40+
let entry = entry?;
41+
42+
if entry
43+
.file_name()
44+
.eq_ignore_ascii_case("swc_noop_plugin.wasm")
45+
{
46+
return Ok(entry.path());
47+
}
48+
}
49+
50+
Err(anyhow!("Could not find built plugin"))
51+
}
52+
53+
// Fake Program
54+
#[ast_node]
55+
#[derive(Eq, Hash, EqIgnoreSpan)]
56+
enum Program2 {
57+
#[tag("Module")]
58+
Module(Module),
59+
#[tag("Script")]
60+
Script(Script),
61+
#[tag("Source")]
62+
Source(SourceString),
63+
}
64+
65+
#[ast_node]
66+
#[derive(Eq, Hash, EqIgnoreSpan)]
67+
struct SourceString {
68+
span: Span,
69+
#[not_spanned]
70+
buf: String,
71+
}
72+
73+
fn internal(rt: Arc<dyn Runtime>, module: &'static CompiledPluginModuleBytes) {
74+
use swc_common::plugin::serialized::VersionedSerializable;
75+
use swc_transform_common::output::capture;
76+
77+
// run single plugin
78+
testing::run_test(false, |cm, _handler| {
79+
eprint!("First run start");
80+
81+
let buf = "console.log(foo)";
82+
let _fm = cm.new_source_file(FileName::Anon.into(), buf);
83+
84+
let span = Span::from((BytePos(0), BytePos(buf.len() as u32)));
85+
let program = Program2::Source(SourceString {
86+
span,
87+
buf: buf.to_string(),
88+
});
89+
90+
let program = PluginSerializedBytes::try_serialize(&VersionedSerializable::new(program))
91+
.expect("Should serializable");
92+
93+
let mut plugin_transform_executor = swc_plugin_runner::create_plugin_transform_executor(
94+
&cm,
95+
&Mark::new(),
96+
&Arc::new(TransformPluginMetadataContext::new(
97+
None,
98+
"development".to_string(),
99+
None,
100+
)),
101+
None,
102+
Box::new(module.clone_module(&*rt)),
103+
Some(json!({ "pluginConfig": "testValue" })),
104+
rt.clone(),
105+
);
106+
107+
let (program_bytes, _captured_output) = capture(|| {
108+
plugin_transform_executor
109+
.transform(&program, Some(false))
110+
.expect("Plugin should apply transform")
111+
});
112+
113+
let program: Program2 = program_bytes
114+
.deserialize()
115+
.expect("Should able to deserialize")
116+
.into_inner();
117+
eprintln!("First run retured");
118+
119+
match program {
120+
Program2::Module(_) | Program2::Script(_) => panic!(),
121+
Program2::Source(source) => {
122+
assert_eq!(source.span, span);
123+
assert_eq!(source.buf, buf);
124+
}
125+
}
126+
127+
Ok(())
128+
})
129+
.expect("Should able to run single plugin transform");
130+
}
131+
132+
#[test]
133+
fn wasmer() {
134+
use swc_plugin_backend_wasmer::WasmerRuntime;
135+
136+
static PLUGIN_BYTES: Lazy<CompiledPluginModuleBytes> = Lazy::new(|| {
137+
let path = build_plugin(
138+
&PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
139+
.join("tests")
140+
.join("fixture")
141+
.join("swc_noop_plugin"),
142+
)
143+
.unwrap();
144+
145+
let raw_module_bytes = std::fs::read(&path).expect("Should able to read plugin bytes");
146+
let module = WasmerRuntime.prepare_module(&raw_module_bytes).unwrap();
147+
148+
swc_plugin_runner::plugin_module_bytes::CompiledPluginModuleBytes::new(
149+
path.as_os_str()
150+
.to_str()
151+
.expect("Should able to get path")
152+
.to_string(),
153+
module,
154+
)
155+
});
156+
157+
tokio::runtime::Runtime::new().unwrap().block_on(async {
158+
internal(Arc::new(WasmerRuntime), &PLUGIN_BYTES);
159+
});
160+
}
161+
162+
#[test]
163+
fn wasmtime() {
164+
use swc_plugin_backend_wasmtime::WasmtimeRuntime;
165+
166+
static PLUGIN_BYTES: Lazy<CompiledPluginModuleBytes> = Lazy::new(|| {
167+
let path = build_plugin(
168+
&PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
169+
.join("tests")
170+
.join("fixture")
171+
.join("swc_noop_plugin"),
172+
)
173+
.unwrap();
174+
175+
let raw_module_bytes = std::fs::read(&path).expect("Should able to read plugin bytes");
176+
let module = WasmtimeRuntime.prepare_module(&raw_module_bytes).unwrap();
177+
178+
swc_plugin_runner::plugin_module_bytes::CompiledPluginModuleBytes::new(
179+
path.as_os_str()
180+
.to_str()
181+
.expect("Should able to get path")
182+
.to_string(),
183+
module,
184+
)
185+
});
186+
187+
tokio::runtime::Runtime::new().unwrap().block_on(async {
188+
internal(Arc::new(WasmtimeRuntime), &PLUGIN_BYTES);
189+
});
190+
}

0 commit comments

Comments
 (0)