swc/crates/swc_ecma_transforms_module/tests/system_js.rs
Levi bfea322351
feat(es/testing): Parse test code as a Program instead of a Module (#9623)
**Description:**

This PR addresses the issue described in https://github.com/swc-project/swc/issues/8713

**BREAKING CHANGE:**
Will break unit tests that use `fold_module`/`visit_module`/`visit_mut_module` if the visitor is intended to work for both modules and scripts instead of using `fold_program`/`visit_program`/`visit_mut_program`.

When creating visitors, you should use `fold_program`/`visit_program`/`visit_mut_program` if you simply want to visit the top-level node.

When creating tests, the input source code will be parsed using `parse_program` by default. If you need to parse it as a `Module`, you can use `module: Some(true)` in `FixtureTestConfig` (or with `test!(module, ..)`), which will parse it as a `Program::Module`, or `Some(false)` for `Program::Script`. `None` will use `parse_program` (`parse_program` will auto-detect the underlying type).
2024-10-08 13:58:58 +09:00

137 lines
2.8 KiB
Rust

#![deny(warnings)]
use std::path::PathBuf;
use swc_common::{chain, Mark};
use swc_ecma_parser::Syntax;
use swc_ecma_transforms_base::resolver;
use swc_ecma_transforms_module::system_js::{system_js, Config};
use swc_ecma_transforms_testing::{test, test_fixture, FixtureTestConfig, Tester};
use swc_ecma_visit::Fold;
fn syntax() -> Syntax {
Syntax::Es(Default::default())
}
fn tr(_tester: &mut Tester<'_>, config: Config) -> impl Fold {
let unresolved_mark = Mark::new();
let top_level_mark = Mark::new();
chain!(
resolver(unresolved_mark, top_level_mark, false),
system_js(Default::default(), unresolved_mark, config)
)
}
test!(
module,
syntax(),
|tester| tr(tester, Default::default()),
allow_continuous_assignment,
r#"var e = {}; e.a = e.b = e.c = e.d = e.e = e.f = e.g = e.h = e.i = e.j = e.k = e.l = e.m = e.n = e.o = e.p = e.q = e.r = e.s = e.t = e.u = e.v = e.w = e.x = e.y = e.z = e.A = e.B = e.C = e.D = e.E = e.F = e.G = e.H = e.I = e.J = e.K = e.L = e.M = e.N = e.O = e.P = e.Q = e.R = e.S = void 0;"#
);
test!(
module,
syntax(),
|tester| tr(
tester,
Config {
allow_top_level_this: true,
..Default::default()
}
),
allow_top_level_this_true,
r#"export var v = this;"#
);
test!(
module,
syntax(),
|tester| tr(
tester,
Config {
allow_top_level_this: false,
..Default::default()
}
),
iife,
r#"
(function(a) {
this.foo = a;
})(this);
"#
);
test!(
module,
syntax(),
|tester| tr(
tester,
Config {
allow_top_level_this: false,
..Default::default()
}
),
top_level_this_false_class,
r#"
const a = this;
class A {
constructor() {
this.a = 1;
}
test() {
this.a = 2;
}
}"#
);
test!(
module,
syntax(),
|tester| tr(
tester,
Config {
allow_top_level_this: false,
..Default::default()
}
),
allow_top_level_this_false,
r#"export var v = this;
function a() {
function d () {}
var b = this;
} "#
);
test!(
module,
syntax(),
|tester| tr(tester, Default::default()),
imports,
r#"
import.meta.url;
import.meta.fn();
await import('./test2');
"#
);
// TODO: test get-module-name-option, tla
#[testing::fixture("tests/fixture/systemjs/**/input.mjs")]
fn fixture(input: PathBuf) {
let dir = input.parent().unwrap().to_path_buf();
let output = dir.join("output.mjs");
test_fixture(
syntax(),
&|tester| tr(tester, Default::default()),
&input,
&output,
FixtureTestConfig {
module: Some(true),
..Default::default()
},
);
}